【问题标题】:Moq - Verify no methods were called except oneMoq - 验证没有调用任何方法,除了一个
【发布时间】:2018-01-15 17:02:49
【问题描述】:

我有一个控制器,它的方法读取配置以确定要调用的其他方法。根据配置,它可能会调用零个、一个或所有 WorkerMethodN() 方法。

public class MyController
{
   public virtual bool EntranceMethod()
   {
      // read configuration to determine which methods to call
   }

   public virtual void WorkerMethod1() { ... }
   public virtual void WorkerMethod2() { ... }
   public virtual void WorkerMethod3() { ... }
}

我正在尝试测试这个EntranceMethod(),我的第一个测试是确定配置为空时的行为。当配置什么都不返回时,我想确保没有调用任何WorkerMethodN() 方法。

到目前为止我的测试:

[TestMethod]
public void ShouldNotCallAnyMethodsWhenConfigurationReturnsNull()
{
   this.mockConfigurationReader
       .Setup(cr => cr.GetEnabledConfigurations())
       .Returns((IEnumerable<Configuration>)null);

   Mock<MyController> mockController =
      new Mock<MyController>(MockBehavior.Strict, this.mockConfigurationReader.Object);

   mockController.Object.EntranceMethod();

   // todo: verify no additional methods are called
}

当调用EntranceMethod() 时,此调用失败并出现异常:invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.

如何使用MockBehavior.Strict 并设置我的控制器调用EntranceMethod() 并验证没有调用其他方法?如果我在EntranceMethod() 上调用.Setup(),它不会运行我想要的实际代码。但是如果我不打电话给.Setup(),我会得到一个例外。

【问题讨论】:

  • 当前状态的问题不清楚,因为它不完整。阅读How to Ask,然后提供minimal reproducible example,可用于重现您的问题,从而更好地理解所询问的内容。
  • 删除MockBehavior.Strict,启用CallBase = true,然后设置并检查其他方法没有使用.Verify(......., Times.Never())调用

标签: c# unit-testing mocking moq


【解决方案1】:

仅出于演示目的,假设如下

public class Configuration {

}

public interface IConfigurationReader {

    IEnumerable<Configuration> GetEnabledConfigurations();
}

public class MyController {
    private IConfigurationReader configReader;


    public MyController(IConfigurationReader configReader) {
        this.configReader = configReader;
    }

    public virtual bool EntranceMethod() {
        // read configuration to determine which methods to call
        var config = configReader.GetEnabledConfigurations();

        //...code for example purposes only
        if (config != null) {
            WorkerMethod1();
            WorkerMethod2();
            WorkerMethod3();
            return true;
        }

        return false;
    }

    public virtual void WorkerMethod1() {
        //... 
    }
    public virtual void WorkerMethod2() {
        //... 
    }
    public virtual void WorkerMethod3() {
        //... 
    }
}

删除MockBehavior.Strict,启用CallBase = true,然后设置并检查其他方法未被使用.Verify(......., Times.Never())调用

[TestClass]
public class MyControllerTest {
    [TestMethod]
    public void ShouldNotCallAnyMethodsWhenConfigurationReturnsNull() {
        //Arrange
        var mockConfigurationReader = new Mock<IConfigurationReader>();
        mockConfigurationReader
            .Setup(cr => cr.GetEnabledConfigurations())
            .Returns((IEnumerable<Configuration>)null);

        var mockController = new Mock<MyController>(mockConfigurationReader.Object) {
            CallBase = true
        };

        //Act
        mockController.Object.EntranceMethod();

        //Assert
        // todo: verify no additional methods are called
        mockController.Verify(_ => _.WorkerMethod1(), Times.Never());
        mockController.Verify(_ => _.WorkerMethod2(), Times.Never());
        mockController.Verify(_ => _.WorkerMethod3(), Times.Never());
    }
}

参考Moq Quickstart

【讨论】:

    【解决方案2】:

    现代答案(最小起订量 4.8 或更高版本):

    mock.Verify(...);
    mock.VerifyNoOtherCalls();
    

    该代码做了两件事:

    1. 验证是否进行了任何预期调用
    2. 验证没有进行其他调用

    来源:Moq Quickstart

    【讨论】:

      猜你喜欢
      • 2011-03-11
      • 1970-01-01
      • 2010-10-06
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多