I'm looking at converting some of our complex creation code to use an IoC container, Autofac, and because I'm a great believer in TDD, I'm writing unit tests for the Module configuration.
Most of the functionality is very easy to test e.g.
var obj = container.Resolve<IThing>();
Assert.IsInstanceOfType(obj, typeof(ThingImplementer));
But we have a number of cases where we have multiple implementers of the same interface and different implementers are being passed to different concrete classes. I've resolved this by using named registration e.g.
builder.RegisterType<ThingImplementer>().Named<IThing>("Implementer1");
builder.RegisterType<OtherImplementer>().Named<IThing>("Implementer2");
builder.Register(c => new Foo(c.ResolveNamed<IThing>("Implementer1"))).As<IFoo>();
What I can't figure out is an easy way to write a unit test for ensuring that Foo gets ThingImplementer and not OtherImplementer. I'm wondering if it is worth the effort, we do have high level integration tests that cover this, but they don't give the documentation or refactoring benefits that unit tests do.
Would you write a unit test for this? If so, how?
You would typically not test the configuration of your container in your unit tests. In your unit test environment you don't use a container to inject any dependencies (you do this by hand) and if you would do this, you would inject fake objects, and not the real/production types. Therefore the container configuration is typically unknown to your unit tests.
What I tend to do sometimes is test whether the container is able to create the application's root types (such as the controller classes of a MVC application, or the Page classes of an WebForms application). Because the container will instantiate a graph of objects, it will give me a good idea whether the container is configured correctly. However, I'm never interested if the container returns the correct implementation. Most of the time there is even only one implementation of a registered interface that is accessible for the application root, so it hardly could go wrong.
If you want to test your container configuration, perhaps it is too complex and you should try to simplify your application design so you can simplify the registration.
Nothing new here, just extensions of Steven's points.
As Steven says, that's definitely not a Unit Test. You could perhaps view it as a learning test. Have a look at the Ninject test suite - it shows how they do such tests (but remember they're writing a Container). I assume autofac has similar tests.
Having said that, if you feel there's interesting behavior and it wont become flaky, it's not harm to stick it into an integration suite.
The other point regarding the fact that it's external is also very valid - see the notion of an Onion Architecture
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With