Ninject.RhinoMocks: Auto Mocking Container For .NET 3.5 and Compact Framework 3.5
Earlier today, I decided I was tired of calling RhinoMocks directly. I love RhinoMocks. It’s a great tool and I don’t want to write tests without it (or another mocking framework like Moq or whatever…). But I’m tired of all the boring “declare a variable here, mock the object there, pass the object to the constructor here” junk that I have to do to get a mock object into my class under test.
Here’s an example of what I’m talking about:
1: public class when_doing_something: basecontext
3: private ISomeView View;
4: private SomePresenter Presenter;
6: public override void EstablishContext()
8: View = MockRepository.GenerateMock<IView>();
9: Presenter = new Presenter(View);
12: public override void When()
18: public void it_should_show_something()
20: View.AssertWasCalled(v => v.ShowThatThing());
Line 3: declare a variable here
Line 8: mock the object here
Line 9: pass it to the class under test
Line 20: assert against it
It’s even more annoying when I have to mock things that I don’t care about, or when I have 5 or 6 or more things to mock (and yes, I know that having that many dependencies is a design smell. I’m not working on a pure greenfield app, so I don’t have the luxury of designing everything ‘correctly’).
… what can I say… I’m lazy. I’d rather ignore the ceremony of declaring the variable, mocking it and passing it to my class. Let me get my class and ask for the mock if I need it. I’m not trying to do anything crazy or bad, or let myself get away with poor design problems. I’m just trying to reduce the amount of code that I have to write in my tests. Maybe it’s the ruby developer in me, lashing out against the ceremony of C# again… whatever it is, I want an auto-mocking container for ninject and rhino mocks.
Now I know there is a general sense of “NO!!!!!” in the alt.net crowd these days… but I don’t understand that. Just because you can abuse a tool, doesn’t mean you should or will. I like wielding triple-edged swords with poison-tip spikes on the handle. It give me power and flexibility to get things done… and yes, the occasional debilitating injury… but hey, a little pain just means I’m learning what not to do, right? 🙂
Automocking With Ninject And RhinoMocks
After doing a bit of googling, I found a stack overflow question with the basic code to get this running. I had a hard time getting that to work, though, so I scrapped it and started fresh from a copy of ninject.moq. A little while later, I have a basic working auto-mocking container for ninject and rhino mocks.
Now I can create a MockingKernel in my basecontext class and change my test code to run like this:
1: public class when_doing_something: basecontext
3: private SomePresenter Presenter;
5: public override void EstablishContext()
7: Presenter = mockingKernel.Get<SomePresenter>();
10: public override void When()
16: public void it_should_show_something()
18: mockingKernel.Get<IView>().AssertWasCalled(v => v.ShowThatThing());
Line 18: get the view and assert against it
There’s only a few lines of code difference in this simple example, so it seems like a wash. When you are dealing with multiple dependencies, though, it makes the code much easier to write.
As a real-world example, after implementing this, I was able to reduce my test code by about 12 lines because I only needed 2 of the mocked objects for assertions. The rest of them were there for ‘support’ and other behaviors, but needed to be there to prevent null reference exceptions. With the auto mocking container in place, I didn’t need to declare a variable, mock, or pass the other dependencies into the class under test. I let the auto-mocking container do that for me.
Ninject.RhinoMocks And Ninject.RhinoMocks.CF
If you’d like to use this functionality, you can grab the source code from github. There are two different version available – one for full .net 3.5 and another for .net 3.5 compact framework.
Please note, though, that I wrote this code for me and built in the behavior that I wanted. All mocked objects are essentially singleton instances so every time you request one from the kernel, it returns the same one. Be sure to call kernel.Reset(); in your teardown, so you don’t get mock objects bleeding over between test fixtures.
Also note that this code is a bit of a hack, as I am not entirely sure about the implementation needs of ninject. I’ve asked for Ian Davis’ input on the code and he’s said he’ll review it… but until that happens, and until I get a chance to “clean up” the code, there’s no promises about the quality of this work.
- .NET: v3.5, Full Framework
- URL: http://github.com/derickbailey/ninject.rhinomocks
- Ninject: v2.0.1
- RhinoMocks: v3.6
- .NET: v3.5, Compact Framework
- URL: http://github.com/derickbailey/ninject.rhinomocks.cf
- Ninject: v2.0.1, compiled for Compact Framework
- RhinoMocks: v3.5 compiled for Compact Framework, with Castle.Core and Castle.DynamicProxy2 as separate dlls