views:

24

answers:

2

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
+1  A: 

If you want to assert that only the methods you have specified are called, you might want to consider using a strict mock for the _mockView in this test.

David M
I want to specify that the UpdateStatus method is not called for the third AuctionClosedFor call - i.e. I want to clear any UpdateStatus expectations set on the mock just before the third call and assert that the method is not called (for an item which has not be added to the sniper)
Gishu
+1  A: 

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?

Grzenio