Our comparison of Rhino Mocks, Moq and NSubstitute continues with a look at how these frameworks support interaction based testing (whether that’s a good idea or not is not going to be dealt with here!).

The idea behind interaction based testing is checking if our class under test makes appropriate calls to the mocked objects.  Typically this is done when testing against API’s that want things done in a certain order or where you want to check that the Save method of a repository was called, as an example.

For our example code we’re going to be testing that the Keeper makes the appropriate call to check the current flea count and then, because the flea count is low, does not try and clean the monkey, i.e. Monkey.Clean() should not be called.

Note that code for the classes under test is in Part 1 of this series.

Rhino Mocks

[Fact]
public void Rhino_method_was_called()
{
var monkey = MockRepository.GenerateMock<IMonkey>();
var keeper = new ZooKeeper {AssignedMonkey = monkey};
monkey.Stub(m => m.CurrentFleaCount()).Return(0);

keeper.CleanMonkey();

monkey.AssertWasCalled(m => m.CurrentFleaCount());
monkey.AssertWasNotCalled(m => m.Clean());
}

So in the initial arrange section of our test we stub out the CurrentFleaCount() call to return zero fleas when called.

We then perform the Act part of our test and ask the Keeper to clean the monkey.

Finally in the Assert part of our test we check if the monkey had methods called on it – the CurrentFleaCount method should be called, and the Clean method should not be called.

If you’re playing along at home, you may have noticed that changing the monkey’s flea count to 100 still makes the test pass, when we should have expected the test to fail (because the clean method should now be called).  This won’t happen because there is a second guard clause in the keeper’s CleanMonkey() method that checks if the monkey is awake and this will always return false.

It brings up an important point with all mock objects in that the default response for any method not explicitly stubbed out is to return the default value, and the default for a bool is false.

Moq

[Fact]
public void Moq_method_was_called()
{
var monkey = new Mock<IMonkey>();
var keeper = new ZooKeeper() {AssignedMonkey = monkey.Object};

monkey.Setup(m => m.CurrentFleaCount()).Returns(0);

keeper.CleanMonkey();

monkey.Verify(m => m.CurrentFleaCount());
monkey.Verify(m => m.Clean(), Times.Never());
}

The code here is similar to Rhino’s code however you’ll notice that to configure our mock object in Moq we use Setup instead of Stub/Expect calls to set the return behaviour for the flea count method.

Moq uses a single Verify method to check that a call was made, so to check that something wasn’t called you have to check that it was called zero times – expressed in Moq syntax as Times.Never().  Make your own mind up over whether this is clear enough from a readability perspective, but I find that it feels a little like Yoda has been writing code and the Verify call seems like it should have a boolean statement for its parameter, not be asserting that a method was called.

NSubstitute

[Fact]
public void Nsubstitute_method_was_called()
{
var monkey = Substitute.For<IMonkey>();
var keeper = new ZooKeeper { AssignedMonkey = monkey };
monkey.CurrentFleaCount().Returns(0);

keeper.CleanMonkey();

monkey.Received().CurrentFleaCount();
monkey.DidNotReceive().Clean();
}

Firstly, not the lack of lambda methods anywhere in this code.  The mock object behaviour is setup by simply attaching a .Returns(0) to the monkey.CurrentFleaCount() method making the code more expressive and simpler to read.

As far as the asserts are concerned we check that a call was Received() by our mock object or that the mock DidNotReceive() the call.  I find this syntax better than the other frameworks in that there’s no lambdas, but it doesn’t read quite as well as I might like.

 

The verdict: It’s a split decision between Rhino and NSubstitute, with me wanting the best of both.

 

Other posts in this series: