Wednesday, May 12, 2010

Mocking or Stubbing IUnityContainer

If you ever want to mock the IUnityContainer interface to return particular instances of objects without have to configure the full container, there are some tricks you will need. Unfortunately, you can't just mock or stub the IUnityContainer interface - it seems to work if you have a debugger attached, but if you are just running the test normally, it will fail with a BadImageFormatException. Nice.

It turns out you can mock or stub the UnityContainerBase class, but you can't just mock the Resolve<T> method call as it has not been marked as virtual. However, there is an abstract method in this class that is called into by the Resolve<T> method. Mock or stub it like follows:

var dialog = MockRepository.GenerateStub<IEditDialog<Attachment>>();
dialog.Stub(x => x.DialogResult).Return(result);
var container = MockRepository.GenerateStub<UnityContainerBase>();
container.Stub(x => x.Resolve(typeof(IEditDialog<Attachment>), null)).Return(dialog);

The container object will now return the stub generated in the first line when Resolve<IEditDialog<Attachment>>() is called. Not particularly neat, but neater than configuring the container!

Labels: , ,


Blogger Paul said...

I've never had to mock my IOC tool, because I avoid calls to Resolve - ideally you would only have one line of code that uses this method in your entire application. For example, in an ASP.NET MVC app, your controller factory would call Resolve, but nothing else would.

Sounds like a discussion topic when we next meet for lunch!

1:05 PM  
Blogger Dale Anderson said...

I agree - class dependencies should usually be provided through an injection mechanism (eg constructor or property injection), but misuse of the IoC is unfortunately rife in my project, something I have been unable to stamp out (to my detriment!)

Having said this, there are also situations where it actually makes sense - in WPF, you bind commands to UI elements such as buttons. We have a ShowEditDialogCommand which will open a dialog to edit a specific object. Given that we don't know if the command will actually be executed, we don't want to instantiate the expensive dialog and pass it to the command, so the command instantiates the dialog itself using the IoC container. To test this command, we stub the IoC container and return a stubbed implentation of the dialog.

There may well be a better solution to this!

3:45 PM  

Post a Comment

<< Home