要模拟对象,它必须是实现接口还是标记虚拟?

mrb*_*lah 6 moq

或者该类是否也可以实现抽象类?

Mar*_*ann 16

要模拟一个类型,它必须是一个接口(这也称为纯虚拟)或具有虚拟成员(抽象成员也是虚拟的).

通过这个定义,您可以模拟虚拟的所有内容.

从本质上讲,动态模拟不会做任何你不能手工完成的事情.

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

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)

动态模拟库也可以这样做,抽象方法也是如此.

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

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