Injecting Rhino Mocks with Ninject
January 20th, 2010So today I hit a hat trick. I needed to test a class that had an injected dependency, and needed some functionality that I didn’t want to add to a fake and would rather isolate to the test. I needed to use a mocking framework. This is my first time using mocks (and only my second week of dependency injection) so this may not use best practices, but this _is_ a blog after all.
I’m using Ninject 2 for dependency injection, NUnit 2.5.3 for unit testing, and Rhino Mocks 3.6 for mocking. NUnit has a mocking framework built in but it doesn’t use strong typing, which I think was causing problems with Ninject.
What I’m really showing here is an example of how to inject a dynamically declared mock instead of a concrete fake. The fact that it is in the context of a test is actually irrelevant, but using mocks and fakes are obviously important in testing to reduce the complexity of the test.
Initially I’m using the default ConcreteFoo implementation of IFoo in the test. This test fails as intended:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
using NUnit.Framework;
using Rhino.Mocks;
namespace Trifecta
{
public interface IFoo
{
string Name { get; }
}
public class ConcreteFoo : IFoo
{
public string Name { get { return "You don't want to see me"; } }
}
public class FooConsumer
{
[Inject] public IFoo Foo { get; set; }
public FooConsumer() {}
}
[TestFixture]
public class FooConsumerTestFixture
{
IKernel Kernel { get; set; }
[SetUp]
public void SetUp()
{
// This is the standard setup that will need to be overridden in the
// test.
Kernel = new StandardKernel();
Kernel.Bind<IFoo>().To<ConcreteFoo>();
}
[Test]
public void FooConsumerGetsTheFoo()
{
// This test depends on a specific behaviour in IFoo, but ConcreteFoo
// is going disappoint right now.
var fooConsumer = Kernel.Get<FooConsumer>();
Assert.That(fooConsumer.Foo.Name, Is.EqualTo("The foo for you"));
}
}
}
Settting up and binding the mock is all done in the test method. The mock IFoo instance is created, and the functionality that the test requires is added. IFoo is then bound to a delegate which returns the mock instance. The binding has a condition that causes the mock binding to be used rather than the ConcreteFoo binding, this seems to be easier then setting up the kernel from scratch for the test (possibly I’m just missing how to rebind).
[Test]
public void FooConsumerGetsTheFoo()
{
// Create a mock implementation of IFoo that has the behaviour the test requires
var mocks = new MockRepository();
var mockFoo = mocks.StrictMock<IFoo>();
Expect.Call(mockFoo.Name).Return("The foo for you");
mocks.ReplayAll();
// Bind the mock when injecting IFoo into FooConsumer. This overrides the binding
// created in SetUp()
Kernel.Bind<IFoo>().ToMethod(context => mockFoo).WhenInjectedInto<FooConsumer>();
// fooConsumer's Foo should now be the mock IFoo created above
var fooConsumer = Kernel.Get<FooConsumer>();
Assert.That(fooConsumer.Foo.Name, Is.EqualTo("The foo for you"));
}
The test should now pass.
