While StructureMap is definitely my IoC container of choice, it’s not the only game in town. At my new job, our existing project uses Ninject. One of my first tasks at this new job was integrating my SpecsFor “framework” into the existing projects. The original version of SpecsFor worked with StructureMap and leveraged its auto-mocking container. While Ninject has an auto-mocking extension, ninject.moq, it is sorely lacking when compared to StructureMap’s offering. In this post, I’ll show you how to modify it into a useful automocking container, and I’ll also show you how easily SpecsFor can be adapted to Ninject using this working container.

Fixing Ninject.Moq

Ninject’s auto-mocking extension project can be found on github. Yes, you have to build it from source if you want to use it. However, don’t bother: the existing approach to auto-mocking is flawed and doesn’t work. Here’s a very simple test case to illustrate the problem:

That’s right, the container returns a new mock every time, which makes it difficult to setup expectations to be injected into a class. It also can’t create the class-under-test directly without jumping through some additional hoops. You have to bind the class to itself, like so:

[Test]
public void Kernel_can_create_class_under_test()
{
var kernel = new MockingKernel();
//Why should I have to do this??
kernel.Bind<DummyClass>().ToSelf();
Assert.IsNotNull(kernel.Get<DummyClass>());
}

Fortunately, these problems are easy to fix, and in fact Derick Bailey has already fixed them in his port of ninject.moq to Rhino Mocks. You can check out his code on github.

First, we need to eliminate the self-binding requirement for the class under test. We can do that by adding a little extra logic to the MockingKernel’s HandleMissingBindingMethod:

If a type is self-bindable, we’re binding it to itself with singleton scope. This means we’ll get the same instance of the class under test from our mocking kernel every time we request it until we call the kernel’s Reset method.

So, that eliminates the need for self-binding our class under test, but we still have the issue of the container returning brand new mocks every time we request one. That’s because the container is using instance scope instead of singleton scope for the mocks. Again, we can fix this by modifying the HanldeMissingBinding method, which should now look like this in its entirety:

With this change in place, both our test classes now pass! You can check out this code on my ninject.moq fork on github. I’ve submitted a pull-request, so hopefully the fixes will eventually be merged back into the main ninject.moq extension.

Using Ninject.Moq with SpecsFor<T>

With a working auto-mocking container in hand, all that remained was modifying SpecsFor to work with ninject.moq instead of StructureMap’s auto-mocking container. I just swapped to the MockingKernel and explicitly created the class under test (StructureMap’s auto-mocking container creates the class under test for you automatically):

About Matt Honeycutt...

Matt Honeycutt is a software architect specializing in ASP.NET web applications, particularly ASP.NET MVC. He has over a decade of experience in building (and testing!) web applications.
He’s an avid practitioner of Test-Driven Development, creating both the SpecsFor and SpecsFor.Mvc frameworks.

He's also an author for Pluralsight,
where he publishes courses on everything from web applications to testing!