Moq:如何清除模拟对象的期望?

时间:2010-06-27 07:53:08

标签: unit-testing moq

一个例子 - 我想测试狙击手只通知视图是否有添加的项目。

[Test]
    public void NotifiesViewOfLoss_IfCloseEventReceivedForSnipedItems()
    {
        _sniper.AddItem(TestConstants.ItemNo54321);
        _sniper.AddItem(TestConstants.ItemNo65432);

        _sniper.AuctionClosedFor(TestConstants.ItemNo65432);
        _mockView.Verify(view => view.UpdateStatus(TestConstants.ItemNo65432, AuctionSniperStatus.Lost));

        _sniper.AuctionClosedFor(TestConstants.ItemNo54321);
        _mockView.Verify(view => view.UpdateStatus(TestConstants.ItemNo54321, AuctionSniperStatus.Lost));

        _sniper.AuctionClosedFor(7);

        // doesn't work
        //_mockView.Verify(view => view.UpdateStatus(It.IsAny<int>(), It.IsAny<AuctionSniperStatus>()),
        //                Times.Never() );
    }

Times.Never行不起作用 - 因为它与之前的一个调用匹配。 我知道还有其他选择:

  • 设置一个新的期望,如果被调用则抛出(如上所示)
  • 喜欢指定7而不是IsAny()
  • 将测试分成2个测试

3 个答案:

答案 0 :(得分:1)

如果要声明,则调用您指定的方法,您可能需要考虑在此测试中对_mockView使用严格模拟。

答案 1 :(得分:1)

在这种情况下,更新视图状态并没有给你任何“结果”你可以断言,我也会去严格的模拟。这样就可以完全设置您希望在模拟对象上进行的调用(以及这些调用的确切数量)。当您更改模拟的类型时,您的测试将立即变为正确。

这种方式比前两个选项要好得多(因为即使你没有猜到正确的参数值也忘记了测试,或者忘记设置会引发异常的期望),它也更具可读性(至少恕我直言)。

关于拆分测试,始终建议尽可能减少单元测试。所以问题是你想测试在两次正确的通话后你有这个错误的电话会发生什么吗?或者仅仅有一次不正确的电话就足够了吗?

答案 2 :(得分:0)

这是一篇旧帖子,但为了完整起见,Moq现在有办法重置验证计数器(this tutorial):

_sniper.AuctionClosedFor(TestConstants.ItemNo54321);
_mockView.Verify(view => view.UpdateStatus(TestConstants.ItemNo54321, AuctionSniperStatus.Lost));

_mockView.ResetCalls();

_sniper.AuctionClosedFor(7);
_mockView.Verify(view => view.UpdateStatus(It.IsAny<int>(), It.IsAny<AuctionSniperStatus>()),
                 Times.Never() );