Testing a Caliburn Micro bootstrapper

I like to have some tests that ensure I can get everything out of the container that I expect to need, before I fire up the application. (Although others would disagree). I mainly have tests for the composition root(s), i.e. anything I am going to try and resolve at runtime.

When developing a WPF app with Caliburn Micro, the container is owned by a Bootstrapper. Unfortunately, it’s not very testable, as most of the interesting methods are protected (but virtual).

The easiest thing to do is create a Test Specific Subclass, and expose the required methods. And then you will find that the base class attempts to initialize the app in the ctor (unless you can find some way to set a flag to false). Thankfully, that method is virtual too, so you can override it and just keep the bits you need:

    public class AppBootstrapperTests
    {
        private TestBootstrapper bootstrapper;

        [TestFixtureSetUp]
        public void FixtureSetUp()
        {
            this.bootstrapper = new TestBootstrapper();
        }

        [Test]
        public void Shell()
        {
            bootstrapper.GetInstance<IShell>();
        }

        private class TestBootstrapper : AppBootstrapper
        {
            public T GetInstance<T>()
            {
                try
                {
                    return (T)base.GetInstance(typeof(T), string.Empty);
                }
                catch (Exception e)
                {
                    this.WhatDoIHave();
                    throw;
                }
            }

            protected override void StartRuntime()
            {
                this.Configure();
            }

            private void WhatDoIHave()
            {
                foreach (var definition in Container.Catalog.Parts)
                {
                    foreach (var exportDefinition in definition.ExportDefinitions)
                    {
                        Console.WriteLine(exportDefinition);
                    }
                }
            }
        }
    }

UPDATE: Added WhatDoIHave to TestBoostrapper.

StructureMapAssert

Following on from a previous post, here’s an updated set of StructureMap assertions:

public static class StructureMapAssert
{
	public static void AssertSingleton<T>(this IContainer container)
	{
		var instance1 = AssertResolvable<T>(container);
		var instance2 = AssertResolvable<T>(container);
		Assert.That(instance1, Is.SameAs(instance2));
	}

	public static void AssertTransient<T>(this IContainer container)
	{
		var instance1 = AssertResolvable<T>(container);
		var instance2 = AssertResolvable<T>(container);
		Assert.That(instance1, Is.Not.SameAs(instance2));
	}

	public static void AssertHttpRequestScoped<T>(this IContainer container)
	{
		T instance2;
		using (new MockHttpContext())
		{
			var instance1 = AssertResolvable<T>(container);
			instance2 = AssertResolvable<T>(container);
			Assert.That(instance1, Is.SameAs(instance2));
		}
		var instance3 = AssertResolvable<T>(container);
		Assert.That(instance3, Is.Not.SameAs(instance2));
	}

	private static T AssertResolvable<T>(this IContainer container)
	{
		try
		{
			return container.GetInstance<T>();
		}
		catch (Exception)
		{
			Console.WriteLine(container.WhatDoIHave());
			throw;
		}
	}

	private class MockHttpContext : IDisposable
	{
		private readonly StringWriter _stringWriter;
		private readonly HttpContext _httpContext;

		public MockHttpContext()
		{
			_httpContext = HttpContext.Current;
			var httpRequest = new HttpRequest("test.aspx", "http://localhost", "?a=1&amp;b=2");
			_stringWriter = new StringWriter();
			var httpResponse = new HttpResponse(_stringWriter);
			HttpContext.Current = new HttpContext(httpRequest, httpResponse);
		}

		public void Dispose()
		{
			_stringWriter.Dispose();
			HttpContext.Current = _httpContext;
		}
	}
}
public class RegistryTests
{
    private IContainer container;
    [TestFixtureSetUp]
    public void FixtureSetUp()
    {
        container = BootstrapContainer();
    }

    [Test]
    public void SessionFactory()
    {
        container.AssertSingleton<ISessionFactory>();
    }

    [Test]
    public void Session()
    {
        container.AssertHttpRequestScoped<ISession>();
    }

    [Test]
    public void ThingyRepository()
    {
        container.AssertTransient<IThingyRepository>();
    }
}

Testing the lifecycle of components

When using an IoC container I like to have confidence that I can retrieve the components that I think I can (rather than getting an unpleasant surprise at runtime!).

This generally involves bootstrapping the container and writing (integration) tests that resolve the types I need. You won’t generally need a test for every class, as retrieving a root object will fail if any of its dependencies cannot be resolved.

While this is a good start, it’s also useful to test the lifecycle of registered components. For example, you want to ensure that your SessionFactory is a singleton. This calls for some helper assertions! (The examples below are tailored for StructureMap, other containers are available :)

using NUnit.Framework;

namespace Your.Namespace.Here
{
	public class TestingComponentLifecycles
	{
		private IContainer container;

		[TestFixtureSetUp]
		public void FixtureSetUp()
		{
			container = BootstrapContainer();
		}

		[Test]
		public void SessionFactory()
		{
			AssertSingleton<SessionFactory>();
		}

		[Test]
		public void Frobulator()
		{
			AssertTransient<Frobulator>();
		}

		private void AssertSingleton<T>()
		{
			var instance1 = container.Resolve<T>();
			var instance2 = container.Resolve<T>();
			Assert.That(instance1, Is.SameAs(instance2));
		}

		private void AssertTransient<T>()
		{
			var instance1 = container.Resolve<T>();
			var instance2 = container.Resolve<T>();
			Assert.That(instance1, Is.Not.SameAs(instance2));
		}
	}
}