使用RhinoMock或Moq测试方法的内部

lea*_*tes 2 javascript unit-testing rhino-mocks moq mocking

对于这个嘲弄的事情来说,我有几个问题.

如果我错了,请纠正我:Mocking没有初始化真正的方法,即Mocking实际上不会调用你的类的构造函数.相反,它会像查看类的签名并创建具有该签名但没有任何方法功能的对象.如果您只需要该类型的对象但不想测试它的内部结构,例如,如果您实际测试的对象具有依赖性,则此选项非常有用.

我正在尝试测试方法的内部,这是否意味着我必须创建该方法所属的类的实例?

Mar*_*ann 7

简介:动态模拟不会帮助您测试类型的内部,但您不应该首先尝试这样做.


你的描述基本上是正确的,但它比这复杂一点.从本质上讲,动态模拟不会做任何你不能手工完成的事情.

假设您正在编写针对此类接口的编程:

public interface IMyInterface
{
    string Foo(string s);
}
Run Code Online (Sandbox Code Playgroud)

您可以手动创建IMyInterface的特定于测试的实现,忽略输入参数并始终返回相同的输出:

public class MyClass : IMyInterface
{
    public string Foo(string s)
    {
        return "Bar";
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您想测试消费者如何响应不同的返回值,那么这会变得非常重复,因此您不必手动编写测试双打,而是可以为您动态创建它们.

想象一下,动态模拟真的编写类似于上面的MyClass实现的代码(它们实际上并不编写代码,它们动态地发出类型,但它是一个足够准确的类比).

以下是如何使用Moq定义与MyClass相同的行为:

var mock = new Mock<IMyInterface>();
mock.Setup(x => x.Foo(It.IsAny<string>())).Returns("Bar");
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,创建对象时都会调用创建的类的构造.由于接口没有构造函数,因此它通常是默认构造函数(分别是MyClass和动态发出的类).

您可以使用以下具体类型执行相同的操作:

public class MyBase
{
    public virtual string Ploeh()
    {
        return "Fnaah";
    }
}
Run Code Online (Sandbox Code Playgroud)

手动,您将能够从MyBase派生并覆盖Ploeh方法,因为它是虚拟的:

public class TestSpecificChild : MyBase
{
    public override string Ploeh()
    {
        return "Ndøh";
    }
}
Run Code Online (Sandbox Code Playgroud)

动态模拟库也可以这样做,抽象方法也是如此.在这种情况下,调用基类的构造函数,因为这就是.NET的工作原理.

但是,您无法编写覆盖非虚拟或内部成员的代码,也无法编写动态模拟.他们只能做你手边的事.

但是,建议:只通过公共API对内部成员进行单元测试.

警告:以上描述适用于大多数动态模拟,但TypeMock除外,它是不同的......可怕的.