【问题标题】:How to verify that method was NOT called in Moq?如何验证在 Moq 中没有调用该方法?
【发布时间】:2010-10-06 22:37:59
【问题描述】:

如何验证Moq 中没有调用该方法?

它有类似 AssertWasNotCalled 的东西吗?

更新:从 3.0 版开始,可以使用新语法:

mock.Verify(foo => foo.Execute("ping"), Times.Never());

【问题讨论】:

    标签: c# .net moq


    【解决方案1】:

    使用 .AtMostOnce();

    真正测试后,再次调用该方法。如果它抛出一个异常,它就会被调用。

    【讨论】:

    • 断言异常是由模拟框架抛出的,是不是有点太晦涩难懂了?
    • 为什么?只需检查异常的类型。如果它是我最小起订量的一个扔掉,你是安全的。
    • 对 Times.Never 使用验证是一个更好的选择......我同意 alex 的观点,即这个解决方案有效,但绝对是晦涩难懂的。
    【解决方案2】:

    更新:从第 3 版开始,请查看上述问题的更新或以下 Dann 的回答。

    或者,让你的模拟严格,这样如果你调用一个你没有期望的方法,它就会失败

    new Mock<IMoq>(MockBehavior.Strict)
    

    或者,如果您希望您的模拟是松散的,请使用 .Throws( Exception )

    var m = new Mock<IMoq>(MockBehavior.Loose);
    m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
    

    【讨论】:

    • ... 或 Callback() 设置一些可以断言的标志。
    • 同样使用选项#2,您不能在一般的 Teardown 方法中使用 VerifyAll - 它会失败,说没有达到预期;理想情况下测试应该通过的时间。
    • 这并不是真正的“未调用验证”,因为它可能会在方法中被捕获并且仍然有效 - 提供误报!
    • Expect 现已弃用
    • 这可能是 2009 年最好的方法,但现在肯定不是。对不起
    【解决方案3】:

    这在最新版本的 Moq 中不起作用(至少从 3.1 开始),应在 Verify 方法中指定,如 回答。

    其实最好在 Returns 语句后指定.AtMost(0)

    var m = new Mock<ISomething>();
    m.Expect(x => x.Forbidden()).Returns("foo").AtMost(0);
    

    虽然“投掷”也有效,但AtMost(0) 恕我直言更具表现力。

    【讨论】:

      【解决方案4】:

      盗自:John Foster's answer to the question, "Need help to understand Moq better"

      您可能想要测试的一件事是付款方式 当一个 65 岁以上的人被传递到 方法

      [Test]
      public void Someone_over_65_does_not_pay_a_pension_contribution() {
      
          var mockPensionService = new Mock<IPensionService>();
      
          var person = new Person("test", 66);
      
          var calc = new PensionCalculator(mockPensionService.Object);
      
          calc.PayPensionContribution(person);
      
          mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never);
      }
      

      【讨论】:

        【解决方案5】:

        在设置了Times.Never 枚举的测试之后运行验证。例如

        _mock.Object.DoSomething()
        _mock.Verify(service => service.ShouldntBeCalled(), Times.Never);
        

        【讨论】:

        • 这里的关键是,Verify(action, Never) 调用是在调用模拟之后 进行的。我以为它是为稍后调用 VerifyAll() 设置验证(这不起作用工作)
        • 简单有效。谢谢。
        • 不确定是不是因为版本较新,但是如果您使用“MockBehavior.Strict”设置模拟并且不添加设置,那么如果调用该方法,它将失败。无需验证。
        【解决方案6】:

        假设你有这个方法并且你想测试它没有被调用

        //Setup    
        var databaseSessionMock = new Mock<IDatabaseSession>();
        databaseSessionMock.Setup(m => m.Commit()).Returns(true).Verifiable();
        RepositoryFactory.Configure<IDatabaseSession>(databaseSessionMock.Object);
        

        你可以这样测试

        databaseSessionMock.Verify(m => m.Commit(It.IsAny()), Times.Never(), "Database Session mock object was not used");
        

        【讨论】:

          【解决方案7】:

          我意识到这是一个非常古老的问题,但它刚刚出现在我的侧边栏中,我想添加我的解决方案。

          作为设置的一部分,许多单元测试似乎模拟了几个函数,但在测试期间并未使用。

          当然最好启用严格模拟(这意味着任何未明确设置的内容都会引发异常),然后不要设置任何您不希望调用的函数。或者换一种说法,只设置一个测试期望调用的函数,其他的都会抛出异常。

          var thingBeingTested = new Mock<IThink>(MockBehaviour.Strict);
          
          thingBeingTested.ThisWillThrowAnExceptionBecauseItHasNotBeenMocked();
          

          【讨论】:

            猜你喜欢
            • 2011-03-11
            • 1970-01-01
            • 1970-01-01
            • 2012-02-26
            • 2013-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-11
            • 1970-01-01
            相关资源
            最近更新 更多