Recursive mocks (or nested mocks as some people call them) are a feature of the mocking frameworks where they will automatically create mock objects for items they should return if you reference a property or method of that object when setting up expectations. The advantages of doing this are that we have less “arrange” code in our test classes and can focus our efforts more on our act and assert code.
Maybe that explanation of recursive mocks doesn’t clarify things much for you so let’s just look at some code instead and see how Rhino Mocks, Moq and NSubstitute help us out.
public void Rhino_recursive_mocks()
var monkey = MockRepository.GenerateStub<IMonkey>();
monkey.Name = "Spike";
monkey.Stub(m => m.Keeper().AssignedMonkey).Return(monkey);
If you have a look at the code you can see that we create a stub object for the the IMonkey interface. Within that we set up an expectation that when we check which monkey the keeper is assigned to that it should be the monkey object we just created (i.e. we’re setting up a circular object reference).
We don’t need to create a specific IZooKeeper stub object here as Rhino will do that for us and if you step through the test in debug mode you can see that we have a fake object created for us:
The code for Moq is much the same apart from the fact that we have to set up the property behaviour for the monkey’s name and remember if we’re dealing with the mock or the object it’s returning.
public void Moq_recursive_mocks()
var monkey = new Mock<IMonkey>();
monkey.Setup(m => m.Keeper().AssignedMonkey).Returns(monkey.Object);
monkey.SetupProperty(m => m.Name);
monkey.Object.Name = "Spike";
Interestingly, if you look at the code in the final assert closely you’ll see that the mock/object distinction is lost when we start using the recursive mocks. Instead of using Keeper().Object.AssignedMonkey we just have Keeper().AssignedMonkey. It’s not a big deal, but it seems to break the paradigm that Moq has used elsewhere of separating the Mock from the object itself.
And finally the NSubstitute approach
public void Nsubstitute_recursive_mocks()
var monkey = Substitute.For<IMonkey>();
monkey.Name = "Spike";
Nice and clean. No lambdas. Expressive and direct. What more could you want :-)
P.S. At time of writing the recursive behaviour was only available when building from source.
The verdict? NSubstitute is the clear winner here.
Other posts in this series: