Moq - 验证除了一个

时间:2018-01-15 17:02:50

标签: c# unit-testing mocking moq

我有一个带有方法的控制器,该方法读取配置以确定要调用的其他方法。根据配置,它可以调用零{,1}或所有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
}

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

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

1 个答案:

答案 0 :(得分:0)

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

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