单元测试c#模拟接口,由另一个接口组成
我是个编码新手 我有一门课,单元测试c#模拟接口,由另一个接口组成,c#,.net,unit-testing,xunit.net,C#,.net,Unit Testing,Xunit.net,我是个编码新手 我有一门课,a: public class A { public InterfaceB _b; public A() { _b = new B(); } public string functionA() { if(String.IsNullOrEmpty(_b.GetId())) return String.Empty; else i
a
:
public class A
{
public InterfaceB _b;
public A()
{
_b = new B();
}
public string functionA()
{
if(String.IsNullOrEmpty(_b.GetId()))
return String.Empty;
else if(String.IsNullOrEmpty(_b.GetKey()))
return String.Empty;
else
return _b.GetToken();
}
}
public interface InterfaceB
{
string GetId();
string GetKey();
string GetToken();
}
我想测试function
,在这里我可以深入了解interfaceB
的所有三种方法。在我的单元测试中,我创建了类A
的一个实例,当我调用它时,我无法设置类B
的行为
它不断地冲击db,但是我需要它来处理其他测试用例
如何完全模拟它,以便测试整个逻辑?要能够测试
A
和模拟接口InterfaceB
,您必须编写A
,这样它就不必负责创建InterfaceB
的实例。相反,它通过构造函数接收InterfaceB
的实例
您将一次又一次地看到这种模式:
public A()
{
private readonly InterfaceB _b;
public A(InterfaceB b)
{
_b = b;
}
public string functionA()
{
if(String.IsNullOrEmpty(_b.GetId())) return String.Empty;
else if(String.IsNullOrEmpty(_b.GetKey())) return String.Empty;
else return _b.GetToken();
}
}
这称为依赖注入。这意味着类的依赖关系被“注入”到其中,而不是创建它的类。当我们像这样注入构造函数时,我们也称之为“构造函数注入”,但通常它只是“依赖项注入”。能够像您所问的那样模拟接口是我们使用它的原因之一
一些关键细节:
- 因为
被传递给构造函数,所以InterfaceB
中没有任何内容“知道”实际实现是什么。它可能是任何东西。因此,A
从未与任何具体实现绑定。(这就是为什么您可以“模拟”a
)InterfaceB
- 字段
为\u b
。严格来说,这不是必需的,但这意味着只能从构造函数中设置只读
,并且不能再次更改。这强调了\u b
只接收并使用它。此类从不控制A
是什么。创建\u b
的内容决定了该值是什么A
InterfaceB
的模拟实现,这些实现完全符合您的需要,如
public class MockedInterfaceB : InterfaceB
{
private string _id;
private string _key;
private string _token;
public MockedInterfaceB(string id, string key, string token);
{
_id = id;
_key = key;
_token = token;
}
public string GetId() {return _id};
public string GetKey() {return _key};
public string GetToken() {return _token};
}
然后在单元测试中,您可以使用该实现:
var testA = new A(new MockedInterfaceB("myid","mykey","mytoken"));
您还可以使用类似的工具更轻松地创建这些模拟
当您听说依赖项注入时,通常是在依赖项注入容器(如Castle Windsor、Autofac或Unity)的上下文中。这些都是帮助您实现依赖注入的有用工具。他们值得学习。但是依赖项注入实际上只是关于如何编写类,就像上面的示例中我们“注入”依赖项(
InterfaceB
)在类A
中,为了能够测试A
和模拟接口InterfaceB
,您必须编写A
,以便它不负责创建InterfaceB
的实例。相反,它通过构造函数接收InterfaceB
的实例
您将一次又一次地看到这种模式:
public A()
{
private readonly InterfaceB _b;
public A(InterfaceB b)
{
_b = b;
}
public string functionA()
{
if(String.IsNullOrEmpty(_b.GetId())) return String.Empty;
else if(String.IsNullOrEmpty(_b.GetKey())) return String.Empty;
else return _b.GetToken();
}
}
这称为依赖注入。这意味着类的依赖关系被“注入”到其中,而不是创建它的类。当我们像这样注入构造函数时,我们也称之为“构造函数注入”,但通常它只是“依赖项注入”。能够像您所问的那样模拟接口是我们使用它的原因之一
一些关键细节:
- 因为
被传递给构造函数,所以InterfaceB
中没有任何内容“知道”实际实现是什么。它可能是任何东西。因此,A
从未与任何具体实现绑定。(这就是为什么您可以“模拟”a
)InterfaceB
- 字段
为\u b
。严格来说,这不是必需的,但这意味着只能从构造函数中设置只读
,并且不能再次更改。这强调了\u b
只接收并使用它。此类从不控制A
是什么。创建\u b
的内容决定了该值是什么A
InterfaceB
的模拟实现,这些实现完全符合您的需要,如
public class MockedInterfaceB : InterfaceB
{
private string _id;
private string _key;
private string _token;
public MockedInterfaceB(string id, string key, string token);
{
_id = id;
_key = key;
_token = token;
}
public string GetId() {return _id};
public string GetKey() {return _key};
public string GetToken() {return _token};
}
然后在单元测试中,您可以使用该实现:
var testA = new A(new MockedInterfaceB("myid","mykey","mytoken"));
您还可以使用类似的工具更轻松地创建这些模拟
当您听说依赖项注入时,通常是在依赖项注入容器(如Castle Windsor、Autofac或Unity)的上下文中。这些都是帮助您实现依赖注入的有用工具。他们值得学习。但是依赖项注入实际上只是关于如何编写类,就像上面的示例中,我们将依赖项(InterfaceB
)注入到类A
,实际上,通过使用它,可以在不更改源代码的情况下测试您的方法。
在创建a的实例之前,您可以将B模拟为未来的实例,然后只需修改B的方法行为即可
例如:
[TestMethod,Isolated]
public void AllBMethodReturnStrings_WillReturnSuccess()
{
// Arrange
// Mocking future B's instance
var fakeIB = Isolate.Fake.NextInstance<B>();
var realA = new A();
Isolate.WhenCalled(()=> fakeIB.GetId()).WillReturn("fakeID");
Isolate.WhenCalled(() => fakeIB.GetKey()).WillReturn("fakeKey");
Isolate.WhenCalled(() => fakeIB.GetToken()).WillReturn("success");
// Act
var result = realA.functionA();
// Assert
Assert.AreEqual("success", result);
}
[测试方法,隔离]
public void allb方法返回字符串\u WillReturnSuccess()
{
//安排
//模拟未来B的实例
var fakeIB=Isolate.false.NextInstance();
var realA=新的A();
隔离.WhenCalled(()=>fakeIB.GetId()).WillReturn(“fakeID”);
隔离.WhenCalled(()=>fakeIB.GetKey()).WillReturn(“fakeKey”);
当调用(()=>fakeIB.GetToken()).WillReturn(“成功”);
//表演
var result=realA.functo();
//断言
断言:平等(“成功”,结果);
}
实际上,通过使用,可以在不更改源代码的情况下测试您的方法。
在创建a的实例之前,您可以将B模拟为未来的实例,然后只需修改B的方法行为即可
例如:
[TestMethod,Isolated]
public void AllBMethodReturnStrings_WillReturnSuccess()
{
// Arrange
// Mocking future B's instance
var fakeIB = Isolate.Fake.NextInstance<B>();
var realA = new A();
Isolate.WhenCalled(()=> fakeIB.GetId()).WillReturn("fakeID");
Isolate.WhenCalled(() => fakeIB.GetKey()).WillReturn("fakeKey");
Isolate.WhenCalled(() => fakeIB.GetToken()).WillReturn("success");
// Act
var result = realA.functionA();
// Assert
Assert.AreEqual("success", result);
}
[测试方法,隔离]
public void allb方法返回字符串\u WillReturnSuccess()
{
//安排
//模拟未来B的实例
var fakeIB=Isolate.false.NextInstance();
瓦雷拉