我可以让NSubstitute自动模拟我的具体课程吗?

时间:2013-06-19 03:20:22

标签: nsubstitute

我有一个我正在使用'NSubstitute'进行模拟的接口,它包含返回concreate类的属性,即返回值不是接口。 e.g

public interface ISomething
{
    SomeObj First { get; }
    SomeObj Second { get; }
}

'SomeObj'具体类有一个默认构造函数,但'NSubstitute'总是为这些属性返回'null'。这个类本身不在我的控制之下,所以我不能简单地从接口派生出它。

可以'NSubstitute'嘲笑这些类型的属性吗?或者有没有办法覆盖行为?否则我必须在测试之前手动初始化模拟,这可能是很多代码(即使它通过常用方法重用)。

也许有一个更简单的解决方案,我已经过度了?

2 个答案:

答案 0 :(得分:7)

如果类具有默认(无参数)构造函数并且其所有成员都是虚拟的,则将自动模拟类(请参阅Auto and recursive mocks简介中的注释)。这样做的目的是为了减少不必要的(破坏性的)副作用的可能性,如果我们使用替代品并且突然遇到一个非虚拟的,未被嘲弄的代码路径,在我们认为是假的实例中做坏事。

NSubstitute没有办法覆盖此行为。相反,我建议您通过自己的工厂方法(例如测试项目中的静态Sub.For<T>(...)方法)创建所有替代品,使用NSubstitute生成替代品,然后应用您需要的所有特定初始化规则,比如使用反射来存根每个类属性的值。

希望这有帮助。

可能相关的链接:

答案 1 :(得分:0)

它不算作自动模拟,但你也问过“或者有没有办法覆盖行为?”并且“也许有一个更简单的解决方案,我已经过度了?”

这个答案依赖于你问题中的陈述:

  • SomeObj是一个超出您控制范围的类,我认为它是单独测试的,或者是不可测试的
  • SomeObj有一个默认构造函数

当然,它要求你“在测试之前手动初始化模拟”,但由于你没有告诉我们这个对象是什么,所以不可能知道完全实现需要做多少工作。

public class SomeObj
{
    // Non-virtual to prevent auto-mocking
    public void Dummy() { }
}
public interface ISomething
{
    SomeObj First { get; }
    SomeObj Second { get; }
}
[TestMethod]
public void Test_17182355ms()
{
    ISomething mockedSomething = Substitute.For<ISomething>();

    SomeObj firstObj = mockedSomething.First;
    Assert.IsNull(firstObj);
    mockedSomething.First.Returns(new SomeObj());
    mockedSomething.Second.Returns(new SomeObj());
    firstObj = mockedSomething.First;
    Assert.IsNotNull(firstObj);
}

另一种方法虽然并非没有自身的缺点,但却是为SomeObj提取自己的界面,如下所示:

public interface ISomeObj
{
    void Dummy();
}
public class MySomeObj : SomeObj, ISomeObj
{
}

然后在测试中模拟ISomeObj

相关问题