Testing dependency registrations with Castle Windsor

Until recently one of the most frustrating bugs I have routinely found in my own code is incomplete dependency registrations.

It's a scenario I'm sure everyone is familiar with - you've just written some new components and got the unit tests passing, so now it's time to fire up the application and see your creations in action. Then as soon as the application starts it falls over because you forgot to add your new components to the IOC container, leaving you with unresolvable dependencies.

I would curse my own forgetfulness as I fixed the problem and would often think to myself that it would be really handy if there was a way to test your dependency registrations. I was pleasantly surprised then to find out that Castle Windsor supports exactly these kinds of tests.

The code below is an example unit test using xUnit which will fail if your dependency registrations are not complete - i.e. if one or more component has dependencies which cannot be resolved. I have used Windsor's installer functionality to group my registrations together which helps break up potentially large numbers of dependency registrations into logical groups, as well helping to keep the code DRY when writing these tests.

[Fact]
public void all_dependencies_are_correctly_registered() {
    using(var container = new WindsorContainer()) {     

        //Setup the container
        container.Install(
            new InstallerOne(),
            new InstallerTwo(),
            new InstallerThree()
        );

        //Inspect the container for problems
        var key = SubSystemConstants.DiagnosticsKey;
        var host = (IDiagnosticsHost)container.Kernel.GetSubSystem(key);
        var diagnostic = host.GetDiagnostic<IPotentiallyMisconfiguredComponentsDiagnostic>();
        var problems = diagnostic.Inspect();

        //Iterate over the problems, writing messages to the console
        foreach(IExposeDependencyInfo problem in problems) {

            var message = new StringBuilder();
            var inspector = new DependencyInspector(message);

            problem.ObtainDependencyDetails(inspector);

            Console.Write(message.ToString());
        }

        //Fail the test if there are any problems
        Assert.Equal(0, problems.Count());
    }
}

This test creates a WindsorContainer, configures dependencies via installers, then looks for problems using IDiagnosticHost. Here I have chosen to write individual error messages to the console before failing the test if there are problems but you could just as easily concatenate the messages together and fail the test with that message. The only potential downside of that approach is that if you have multiple missing dependencies the message is going to be quite wordy (and also more informative).

It may not save a huge amount of time, but having a test like this in place removes one more small but annoying gotcha in the development process.

Comments