c# - NSubstitute ForPartsOf...当调用真正的方法时

标签 c# mocking nsubstitute

我正在尝试使用 ForPartsOf<...>() 替换方法然后 subst.Configure().MyMethod(...).Returns(...)subst.When(x => x.MyMethod(..)).Returns(...) , 但在这两种情况下都是真正的 MyMethod被调用。我的印象是Configure()When()应该确保 MyMethod()调用是在“配置模式”下进行的,因此不会进行真正的调用。我错了吗?还是我做错了什么?

下面是我的(大大简化并更改了名称的)代码。对于两者 subst1subst2 , 真正的 NeedsMoreWork使用 item == null 调用方法.

public interface IMyClass
{
    bool NeedsMoreWork(Item item, out Part part);
    bool DoWork(Item item);
}

public class MyClass : IMyClass
{
    private ILogger log;

    public MyClass(ILogger log)
    {
        this.log = log;
    }

    public bool NeedsMoreWork(Item item, out Part part)
    {
        log.Debug($"Examining item {item.Id}");
        part = null;
        if (item.Completed())
        {
            log.Debug($"Item {item.Id} already completed.");
            return false;
        }
        part = item.GetNextPart();
        log.Debug($"Item {item.Id} needs work on part {part.Id}.");
        return true;            
    }

    public bool DoWork(Item item)
    {
        if (!item.NeedsMoreWork(item, out Part part))
            return false;
        log.Debug($"Starting work on part {part.Id}.");
        // Do work on part.
        log.Debug($"Work completed on part {part.Id}.");
        return true;
    }
}

[TestMethod]
public void TestDoWork()
{
    // Version with Configure():
    var subst1 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
    subst1.Configure()
        .NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
        .Returns(false);

    // Version with WhenForAnyArgs():
    var subst2 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
    subst2.WhenForAnyArgs(x => x.NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
        .Returns(false);
}

最佳答案

使用 NSubstitute 时,要模拟/ stub 的成员需要是虚拟才能被覆盖。

引用Partial subs and test spies

public class MyClass : IMyClass {
    private readonly ILogger log;

    public MyClass(ILogger log) {
        this.log = log;
    }

    public virtual bool NeedsMoreWork(Item item, out Part part) { //<-- THIS IS NOW VIRTUAL
        log.Debug($"Examining item {item.Id}");
        part = null;
        if (item.Completed()) {
            log.Debug($"Item {item.Id} already completed.");
            return false;
        }
        part = item.GetNextPart();
        log.Debug($"Item {item.Id} needs work on part {part.Id}.");
        return true;            
    }

    public bool DoWork(Item item) {
        if (!NeedsMoreWork(item, out Part part))
            return false;
        log.Debug($"Starting work on part {part.Id}.");
        // Do work on part.
        log.Debug($"Work completed on part {part.Id}.");
        return true;
    }
}

NeedsMoreWork 现在可以根据需要 stub

[TestMethod]
public void TestDoWork_Should_Return_False() {
    //Arrange
    var subject = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
    bool expected = false;
    subject.Configure().NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>()).Returns(expected);

    //Act
    bool actual = subject.DoWork(new Item());

    //Assert - FluentAssertions
    actual.Should().Be(expected);
}

Note the CAUTION comment. If we had not used Configure() here before .NeedsMoreWork(...) then the real method would have executed before we had a chance to override the behavior. In some cases this may not be a problem, but if in doubt make sure you call Configure() first so NSubstitute knows you are configuring a call and don’t want to run any real code. (This still does not guarantee real code will not run – remember, NSubstitute will not prevent non-virtual calls from executing.)

The Configure() method is only available in NSubstitute 4.0 and above. For verisons prior to 4.0 we need to use When .. DoNotCallBase

注意:强调我的

关于c# - NSubstitute ForPartsOf...当调用真正的方法时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57996835/

相关文章:

c# - 动态地用另一个组合框填充一个组合框

java - 为什么执行模拟方法时没有调用mockito?

java - 使用 Mockito 模拟静态方法

c# - 如何对基于枚举的 switch 语句的默认情况进行单元测试

c# - 安全导航表达式重写器

C#:从泛型类型名称中获取 XML 元素名称的最佳方式

c# - 避免或接受中断编辑并继续的 C# 构造?

c# - 使用 NSubstitute 模拟 Web 服务时出错

c# - 模拟子验证器时 FluentValidation 抛出 NullReference 异常

c# - NSubstitute - 模拟在返回 void 的方法中抛出异常