Testing with the Castle IoC and Rhino
To keep the dust off the blog I thought I would throw a quick post out about something that’s been working pretty well for tdd controllers.
This project is using ASP.NET MVC with some components from Castle Project. It’s using nunit and Rhino mocks.
The controllers are created from the Castle IoC container, so their constructors take service by interface. This can cause a certain churn in the unit testing so we use an instance of DefaultKernel to handle the details of correct ctor parameters and order and whatnot.
The especially nice thing is you can put mock interfaces in the microkernel as well, and they are used to satisfy all dependencies. There’s a simple extension method to make that easier.
public static class MockExtensions
{
public static T Mock<T>(this IKernel kernel) where T : class
{
if (!kernel.HasComponent(typeof(T)))
kernel.AddComponentInstance<T>(MockRepository.GenerateMock<T>());
return kernel.Resolve<T>();
}
}
And you can throw everything you’re testing and all of the mocks into a kernel on test setup.
[TestFixture]
public class AuthorizationControllerTests
{
private DefaultKernel _kernel;
[SetUp]
public void Init()
{
_kernel = new DefaultKernel();
_kernel.Mock<IRepository<UserRecord>>();
_kernel.Mock<IAuthorizationService>();
_kernel.AddComponent<AuthorizationController>();
}
}
Because the kernel will return the same instance of the mocked interface each time it’s needed, the tests themselves can get them from the kernel to set expectations and verify results.
[Test]
public void Model_from_users_action_should_list_user_records()
{
var users = new[]
{
new UserRecord {Name = "foo"},
new UserRecord {Name = "bar"},
};
_kernel.Mock<IRepository<UserRecord>>()
.Expect(x => x.FindAll())
.Return(users);
var controller = _kernel.Resolve<AuthorizationController>();
var result = controller.Users();
Assert.That(result, Is.InstanceOfType(typeof (ViewResult)));
var model = ((ViewResult) result).ViewData.Model;
Assert.That(model, Is.InstanceOfType(typeof(IEnumerable<UserRecord>)));
_kernel.Mock<IRepository<UserRecord>>()
.VerifyAllExpectations();
}
Nice and tidy.
March 9th, 2009 at 6:48 pm
That’s really rather cool, thanks for sharing
March 12th, 2009 at 9:28 am
I like how this is done and I’ll be using this in my future IoC projects. Makes setup of the tests cleaner and easier.
March 12th, 2009 at 9:54 am
Anything that makes your code smaller has got to be good… Within reason… I wonder if the _kernel field should be renamed _? :)