Should you unittest the code that registers components into your IoC container?
If so, how?
Should you unittest the code that registers components into your IoC container?
If so, how?
Since your components might have their own dependencies or perform some initialization I would cover this scenario with UTs.
Something like
iocContainer.Register(typeof(MyService1));
service = iocContainer.Get(typeof(MyService));
Debug.AssertNotNull(service);
In spring you can have a unit test that simply loads the application-context without asserting anything. It's actually a fairly useful test in conjunction with automatic build, since spring complains about a lot of problems when loading the full context.
I am using Windsor in an ASP.NET MVC project where I have written a simple test to verify that all controllers can be instantiated (i.e. their dependencies can be resolved).
I have a test for each configuration of the web site (e.g. "development", "test", "someProductionSite", etc.) where I create my Windsor container with that particular configuration and loop through all non-abstract implementations of IController, checking that I can resolve an instance of each.
Since the controller factory is the only entry point into the application that will result in a container.Resolve(...), I am 100% certain that all configurations are valid.
Generally, I have found that writing tests that function as assertions about the entire system are extremely useful and valuable.
E.g. I am also asserting that all controller actions are virtual, which is a requirement, because I am using Castle's automatic transaction management to surround controller actions with transactions.
@aku, @krosenvold and @mookid make a compelling argument for testing that the configuration of the dependencies is correct.
I don't think that this is unit testing though.
What are you testing? You're not trying to unit test the container itself (presumably that isn't code you wrote or are maintaining).
What you are trying to test is that all the dependencies of a particular type can be created and that the type can be resolved. This sounds like a pretty useful system test or integration test to have in your continuous integration environment.
So once you have binaries that pass unit test, you can create the container and run the set up for the container on a machine that mirrors your production environment and test that each of the types that the container should be able to resolve can actually be created and all of their dependencies can be instantiated.
It would be nice to run this in a fresh VM that you've applied your latest installer to.
It can be useful because some dependency injection frameworks (like Unity) have weird rules for choosing which constructor to call. I would definitely recommend unit testing to make sure the registration and creation of your type happens successfully.
It somehow feels wrong to me to have the IoC container running in my test-projects. I also noticed that most of the bugs that are caused by dependencies not being resolved are caused by the order dependecies are resolved, this is very hard to test right and is not something I'd want to do as a unit test.
Usually I use Debug.Assert statements in the initialization routines of my classes. This gives me an early warning system for IoC related errors and also helps specify dependencies better in my code.
What I do with the Guice IoC container, is that first I produce the classes for some feature using TDD without Guice (these are unit tests). Then I create an integration test for that feature with Guice. At that point the IoC configuration (Guice module) is incomplete, so the integration test will fail. Using TDD, I add the IoC configuration step by step until the integration test passes. I won't add any @Inject annotation, line of configuration or scope declaration, unless it is required to pass a test. As a result, I will have integration (or acceptance) tests making sure that the IoC configuration is right and complete.
This same method should work with any IoC container or other system, whose configuration is so complex that it may break - don't write any configuration unless it is require to pass a test.