对于这个嘲弄的事情来说,我有几个问题。
如果我错了,请纠正我: Mocking没有初始化真正的方法,即Mocking实际上不会调用你的类的构造函数。相反,它会像查看类的签名并创建具有该签名但没有任何方法功能的对象。如果你只需要那种类型的对象但又不想测试它的内部结构,这很有用。如果您实际测试的对象依赖于它。
我正在尝试测试方法的内部,这是否意味着我必须创建该方法所属的类的实例?
答案 0 :(得分:7)
摘要:动态模拟不会帮助您测试类型的内部,但您不应该首先尝试这样做。
你的描述基本上是正确的,但它有点复杂。基本上,动态模拟不会做任何你不能手工做的事情。
假设您正在编写针对此类接口的编程:
public interface IMyInterface
{
string Foo(string s);
}
您可以手动创建IMyInterface的特定于测试的实现,忽略输入参数并始终返回相同的输出:
public class MyClass : IMyInterface
{
public string Foo(string s)
{
return "Bar";
}
}
但是,如果您想测试消费者如何响应不同的返回值,那么这会变得非常重复,因此您可以让框架动态创建它们,而不是编写测试双打。对你而言。
想象一下,动态模拟真的编写类似于上面的MyClass实现的代码(它们实际上并不编写代码,它们动态地发出类型,但它是一个足够准确的类比)。
以下是如何使用Moq定义与MyClass相同的行为:
var mock = new Mock<IMyInterface>();
mock.Setup(x => x.Foo(It.IsAny<string>())).Returns("Bar");
在这两种情况下,创建对象时都会调用已创建类的构造。由于接口没有构造函数,因此它通常是默认构造函数(分别是MyClass和动态发出的类)。
您可以对具体类型执行相同的操作,例如:
public class MyBase
{
public virtual string Ploeh()
{
return "Fnaah";
}
}
手动,您可以从MyBase派生并覆盖Ploeh方法,因为它是虚拟的:
public class TestSpecificChild : MyBase
{
public override string Ploeh()
{
return "Ndøh";
}
}
动态模拟库也可以这样做,抽象方法也是如此。在这种情况下,将调用基类的构造函数 ,因为这就是.NET的工作原理。
但是,您无法编写覆盖非虚拟或内部成员的代码,也无法编写动态模拟代码。他们只能做你手边的事情。
一条建议:仅通过公共API测试内部成员。
警告:上面的描述适用于大多数动态模拟,但TypeMock除外,它是不同的......可怕的。