My last post talked about abstracting the implementation of an IoC container so that you could implement more than one container if you had the need to. One of the coolest uses of this kind of abstraction that I’ve seen in quite some time is what JP Boodhoo did in his Nothin’ But .Net Store codebase. I’m going to summarize it here, but you need to look at the code to see how sweet it really is.
In the code base JP has abstracted his IoC container in a very similar way to what I showed in my previous post. On top of the IoC abstraction he has an implementation of a dependency resolver that gives the programmer one point of coding contact that doesn’t care which container is implemented inside of it.
If you’re looking in the codebase, head on over to the testing project and look through the classes in the \test\xUnit\Utility folder. Here you’ll see that JP has implemented a couple of custom attributes. The purpose of these attributes is to give the developer a way to control, at a test by test level, which IoC container is used when a test is executing. Based on the code in his sample app, JP has run into three different scenarios in that code that he needed to be able to handle.
The first scenario is where the test has no need of an IoC container, which results in no attribute telling the test which container to use. If you’re working on a very pure unit test, this will be the situation that you’re in.
Sometimes you will want your tests to use a container that is configured and implemented just as it would be in production. In that case there is a custom attribute that ensures that the production container is loaded up. Most likely you’d use something like this when you’re working on integration tests.
The last scenario is where you want to test a piece of code that has a dependency on a something from the container. The situation occurring in the Nothin’ But .Net code is one where there is a logging call in the middle of the unit of code being tested. In this specific case there is a call to a logging container that is using a static call. As we know, static calls make testing very difficult. You can’t dependency inject into them. In the case of this logging class, it needs to call the IoC container to load up the logging framework that is being used. Because of this, if you don’t load up the container before executing a unit of code that contains a call to the logging class, it will throw an error when it tries to call the IoC container.
The result is that you need to initialize a container before you launch any test that may have logging used in it. The standard way to do that would be to use the StartUp or TestFixtureStartUp methods in your test suite. What happens if you need to use a different container on test #1 than you do on test #2? This is where JP’s implementation of custom attributes really shines. Throw which ever attribute you want onto the test you’re currently working with and voila, container configured. It does exactly what you need it to and it doesn’t clutter up your tests with a bunch of setup code.
The problem with JP’s implementation? Well, if you’re using MbUnit, there isn’t one. I looked at nUnit and there doesn’t appear to be a way to achieve the same attribute inheritance option. The biggest reason is that the TestAttribute class is sealed up and inherits directly from System.Attribute which stops you from being able to hook the test execution prior to it starting. As a result, the only way that I can get test by test level configuration of my container is to embed the container loading in the tests themselves. Not a great solution, but one I’ll probably end up having to use until I have a second or third reason to convince people to make the move to a different testing framework.