Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq: How to clear expectations on a mock object?

An example - I want to test that the sniper notifies the view only for added items.

[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() );
    }

The Times.Never line doesn't work - because it matches one of the earlier calls. I know that there are other alternatives:

  • set up a new expectation to throw if called (as shown above)
  • like specifying 7 instead of IsAny()
  • splitting the test into 2 tests
like image 646
Gishu Avatar asked Oct 14 '22 03:10

Gishu


1 Answers

In this case, where updating the status on the view doesn't give you any "result" you could assert, I would also go for strict mocks. This way you set exactly the calls you expect to be made on the mocked object (and an exact number of these calls). When you change the type of the mock your test will instantly become correct.

This way is much better than your first two options (because it will fail the test even if you don't guess the correct parameter values or forget to set up the expectation that will throw an exception), it is also more readable (IMHO at least).

Regarding splitting the tests, it is always advisable to keep unit tests as small as possible. So the question is do you want to test what happens when you have this incorrect call after two correct calls? Or is it enough to just have a single incorrect call?

like image 124
Grzenio Avatar answered Oct 18 '22 09:10

Grzenio