最好的接口模拟/假的部分实现
问题描述:
在C#下有一个很好的工具,假部分测试实现复杂的接口(服务,存储库等)?最好的接口模拟/假的部分实现
我目前使用的模拟框架(RhinoMocks)太慢,太难以处理这个目的。
先决条件:
- 没有显著的性能损失,相比于真正的实现(批量测试)
- 实现与基本的逻辑和数据(例如:字典,而不是数据库表)
- 无需更换测试,当界面改变时。
全面推行例如:
public interface IMyInterface
{
int PropertyA { get; set; }
int PropertyB { get; set; }
void DoSomethingWithX(int x);
int GetValueOfY();
}
public class FakeImplementation : IMyInterface
{
private int _valueOfYCalls = 0;
public int PropertyA { get; set; }
public int PropertyB { get; set; }
public void DoSomethingWithX(int x)
{ }
public int GetValueOfY()
{
return _valueOfYCalls++;
}
}
计数器只是模拟了基本的逻辑。
问题是,如果接口得到一个新的方法,如SetSomeZ(int z),测试将不会建立/运行了,没有明确的改变。
有没有一个假的/模拟的框架,使用基本的实现,但通过虚拟/覆盖或包装自动添加成员?
像这样的:
[ImplementsInterface(nameof(IMyInterface))]
public class FakeImplementationBase
{
private int _valueOfYCalls = 0;
[ImplementsMember(nameof(IMyInterface.GetValueOfY))]
public virtual int GetValueOfY()
{
return _valueOfYCalls++;
}
}
工具/框架应在运行时生成全面实现类型,类似于嘲笑/存根,但使用的基本实现,只需添加缺少的接口部分。
这不应该是真正的单元测试,而是为了更复杂的目的。它也是具有丰富接口和类的传统软件,并不太多关于“单一责任”。
答
Moq正是你想要的。
public interface IFoo {
int MethodA(int a);
void MethodB(long b);
void MethodC(string c);
...
}
var MoqFoo = new Mock<IFoo>();
MoqFoo.Setup(m => m.MethodA(It.Is(a => a > 0)).Returns<int>(a => a + 1);
MoqFoo.Setup(m => m.MethodC(It.IsAny<string>()).Callback<string>(c => Debug.Write(c));
请注意我们怎么没有为MethodB做.Setup()?当你声明它时,所有的方法和属性都会得到虚拟方法/属性,.Setup()将会指定你自己定制的方法和属性。所以如果你的接口有10个方法,但你只想测试MethodD(),你只需要为它编写代码。
http://www.developerhandbook.com/unit-testing/writing-unit-tests-with-nunit-and-moq/
谢谢,Moq的表现如何? RhinoMocks有类似的语法,但比实际的类慢得多(只要它们只在内存中)。我想避免RhinoMocks中'.Setup(...)'或'.Stub()'的相当复杂的语法。我期望框架在运行时创建一个新类型,它像一个普通类一样实例化,只进行一次反射,然后像编码类那样执行性能。 –