One of the biggest headaches when it comes to unit tests and test driven development is having to modify existing tests when a constructor changes even if they don’t need to use the newly injected object.
For an introduction to RhinoMocks check out How to write better unit tests using RhinoMocks and stubs.
You might fix the problem by passing in null or writing a line such as the one below
var somethingYouWantToStub = MockRepository.Stub<AnInterface>();
and it to the ever growing lines of creating stub objects.
Anouncer: What if there was a way to write your unit tests where you didn’t have to manually stub out everything up front and existing tests could still run if a constructor changes? Well there is!
Action: Automocking container enters from stage door left.
The code below shows two unit tests for a full name creator which calls various providers to get a first and last name and then concatenates together. Look out for:
- how in the first test (“Can_Create_FullName”) each name provider has to be stubbed out and then added in the constructor for the FullName creator.
- how in the second test (“Can_Create_FullName_Using_AutoMockingContainer”) an auto mocking container is used to create the FullName creator.
- The use of the arrange, act and assert to make the tests easier to follow
using System;
using NUnit.Framework;
using Rhino.Mocks;
namespace AutoMockingContainer
{
public interface IFirstNameProvider
{
string GetFirstName();
}
public interface ILastNameProvider
{
string GetLastName();
}
public class FullNameCreator
{
private readonly IFirstNameProvider _firstNameProvider;
private readonly ILastNameProvider _lastNameProvider;
public FullNameCreator(IFirstNameProvider firstNameProvider, ILastNameProvider lastNameProvider)
{
_firstNameProvider = firstNameProvider;
_lastNameProvider = lastNameProvider;
}
public string Concatenate()
{
var firstName = _firstNameProvider.GetFirstName(); ;
var lastName = _lastNameProvider.GetLastName();
return String.Format("{0} {1}", firstName, lastName);
}
}
[TestFixture]
public class FullNameCreatorTests
{
[Test]
public void Can_Create_FullName()
{
// Arrange
var firstNameProvider = MockRepository.GenerateStub<IFirstNameProvider>();
var lastNameProvider = MockRepository.GenerateStub<ILastNameProvider>();
FullNameCreator fullNameCreator = new FullNameCreator(firstNameProvider, lastNameProvider);
firstNameProvider.Stub(n => n.GetFirstName()).Return("William");
lastNameProvider.Stub(n => n.GetLastName()).Return("Clinton");
// Act
var result = fullNameCreator.Concatenate();
// Assert
Assert.That(result, Is.EqualTo("William Clinton"));
}
[Test]
public void Can_Create_FullName_Using_AutoMockingContainer()
{
// Arrange
var mocks = new MockRepository();
var container = new Rhino.Testing.AutoMocking.AutoMockingContainer(mocks);
container.Initialize();
FullNameCreator fullNameCreator = container.Create<FullNameCreator>();
using (mocks.Record())
{
container.Resolve<IFirstNameProvider>().Stub(r => r.GetFirstName()).Return("William");
container.Resolve<ILastNameProvider>().Stub(r => r.GetLastName()).Return("Clinton");
}
// Act
string result;
using (mocks.Playback())
{
result = fullNameCreator.Concatenate();
}
// Assert
Assert.That(result, Is.EqualTo("William Clinton"));
}
}
}
In the second test we have to apply RhinoMocks record-playback pattern. At this point there is no clear winner.
So now what if client/customer creates the following user story:
As a account administrator
I want to be able to see the first, middle and last name when I retrive customer information
So that I know their full name.
or for you behavior driven development fans
Given a customers’ first name is “William”, second name is “Jefferson” and third name is “Clinton”
When a user wants to retrieve their full name
Then “William Jefferson Clinton” should be returned
Doing this the test driven way, we can assume we will using a MiddleNameProvider and calling a method called ‘GetMiddleName’.
Without auto mocking it’s a case of creating a stubbed object, changing the constructor for the FullNameCreator and then setting up the stubbed object. With auto mocking it’s a one line code change.
[TestFixture]
public class FullNameCreatorTests
{
[TestFixture]
public class FullNameCreatorTests
{
[Test]
public void Can_Create_FullName()
{
// Arrange
var firstNameProvider = MockRepository.GenerateStub<IFirstNameProvider>();
var middleNameProvider = MockRepository.GenerateStub<IMiddleNameProvider>();
var lastNameProvider = MockRepository.GenerateStub<ILastNameProvider>();
FullNameCreator fullNameCreator = new FullNameCreator(firstNameProvider, middleNameProvider, lastNameProvider);
firstNameProvider.Stub(n => n.GetFirstName()).Return("William");
middleNameProvider.Stub(n => n.GetMiddleName()).Return("Jefferson");
lastNameProvider.Stub(n => n.GetLastName()).Return("Clinton");
// Act
var result = fullNameCreator.Concatenate();
// Assert
Assert.That(result, Is.EqualTo("William Jefferson Clinton"));
}
[Test]
public void Can_Create_FullName_Using_AutoMockingContainer()
{
// Arrange
var mocks = new MockRepository();
var container = new Rhino.Testing.AutoMocking.AutoMockingContainer(mocks);
container.Initialize();
FullNameCreator fullNameCreator = container.Create<FullNameCreator>();
using (mocks.Record())
{
container.Resolve<IFirstNameProvider>().Stub(r => r.GetFirstName()).Return("William");
container.Resolve<IMiddleNameProvider>().Stub(r => r.GetMiddleName()).Return("Jefferson");
container.Resolve<ILastNameProvider>().Stub(r => r.GetLastName()).Return("Clinton");
}
// Act
string result;
using (mocks.Playback())
{
result = fullNameCreator.Concatenate();
}
// Assert
Assert.That(result, Is.EqualTo("William Jefferson Clinton"));
}
}
}
It’s not only a reduction in the amount of code we have to write. What you have to remember here is that any changes to the constructor for the FullNameCreator will break the non-auto mocked unit test.
Here’s an example to show what I mean. The customer/client decides they want to add logging. This has nothing to do with our expected outcomes. The code for the ILogger and changes to the FullNameCreator are shown below.
public interface ILogger
{
void Log(string message);
}
public class FullNameCreator
{
private readonly IFirstNameProvider _firstNameProvider;
private readonly IMiddleNameProvider _middleNameProvider;
private readonly ILastNameProvider _lastNameProvider;
private readonly ILogger _logger;
public FullNameCreator(IFirstNameProvider firstNameProvider, IMiddleNameProvider middleNameProvider, ILastNameProvider lastNameProvider, ILogger logger)
{
_firstNameProvider = firstNameProvider;
_middleNameProvider = middleNameProvider;
_lastNameProvider = lastNameProvider;
_logger = logger;
}
public string Calculate()
{
_logger.Log("Getting the first name");
var firstName = _firstNameProvider.GetFirstName();
_logger.Log("Getting the middle name");
var middleName = _middleNameProvider.GetMiddleName();
_logger.Log("Getting the last name");
var lastName = _lastNameProvider.GetLastName();
return String.Format("{0} {1} {2}", firstName, middleName, lastName);
}
}
This solution will not build because a unit test needs amending… no prizes for guessing which one!

At this point we can’t even just pass null, because the code will try and call the Log method. We have to create a stub object and pass it in.
For the unit test using the auto mocking container the addition of the logger made no difference whatsoever.
So am I writing all my tests using the auto mocking container? Sort of. When I’m doing test driven development I don’t like using the record playback syntax, I find it slows me down and takes my focus away from writing good unit tests. However when I have reached a point where the user story is complete and refactoring begins, I would adopt the auto mocking approach.
The other problem is that in order to use the automocking container I have to reference five libraries which is a bit of a pain and could lead to a whole host of version nightmares… more on that in another post.
The code is available at http://code.google.com/p/arrangeactassert/. The solution is in the AutoMockingContainer folder.