StructureMap: How can i unit test the registry class?
Asked Answered
I

3

8

I have a registry class like this:

public class StructureMapRegistry : Registry
{
    public StructureMapRegistry()
    {
        For<IDateTimeProvider>().Singleton().Use<DateTimeProviderReturningDateTimeNow>();
    }

I want to test that the configuration is according to my intent, so i start writing a test:

public class WhenConfiguringIOCContainer : Scenario
{
    private TfsTimeMachine.Domain.StructureMapRegistry registry;
    private Container container;

    protected override void Given()
    {
        registry = new TfsTimeMachine.Domain.StructureMapRegistry();
        container = new Container();
    }

    protected override void When()
    {
        container.Configure(i => i.AddRegistry(registry));
    }

    [Then]
    public void DateTimeProviderIsRegisteredAsSingleton()
    {
        // I want to say "verify that the container contains the expected type and that the expected type
        // is registered as a singleton
    }
}

How can verify that the registry is accoring to my expectations? Note: I introduced the container because I didn't see any sort of verification methods available on the Registry class. Idealy, I want to test on the registry class directly.

Illyrian answered 18/3, 2010 at 11:24 Comment(1)
Its just a rewrite of nunit. The "ThenAttribute" inherites from "TestAttribute" and the scenario is an abstract TextFixture with the methods Given and When executed in [SetUp]Illyrian
D
3

Think of a Registry class like a config file - it doesn't really make sense to test it in isolation, but you might want to test how another class responds to it. In this case, you would test how a Container behaves when given a registry, so you were on the right track by introducing the Container to your test.

In your test, you can request an IDateTimeProvider and assert that the concrete type returned is the type you expect. You can also retrieve 2 instances from the container and assert that they are the same instance (ReferenceEquals) to verify the singleton behavior.

Din answered 21/3, 2010 at 20:15 Comment(0)
O
3

Within StructureMap a registry is used to generate a PluginGraph; so to unit test a registry you need to check that it's design produces the correct graph. Unfortunately test verification is best done against an internal property, here's a sample:

public interface IFoo {}

public class SomeFoo : IFoo {}

public class FooRegistry : Registry
{
  public FooRegistry()
  {
    For<IFoo>().Use<SomeFoo>();
  }
}

[TestFixture]
public class FooRegistryTests
{
  [Test]
  public void ForIFoo_UseSomeFoo_AsDefaultInstance()
  {
    // Arrange
    var registry = new FooRegistry();

    // Act
    var pluginGraph = registry.Build();
    var iFooPluginFamily = pluginGraph.FindFamily(typeof(IFoo));
    var defaultInstance = iFooPluginFamily.GetDefaultInstance();

    // Assert
    Assert.IsTrue(defaultInstance.UsesConcreteType<SomeFoo>());
  }
}

public static class TestExtensions
{
  public static bool UsesConcreteType<T>(this Instance instance)
  {
    var concreteTypeProperty = typeof (Instance).GetProperty("ConcreteType", BindingFlags.Instance | BindingFlags.NonPublic);
    if (concreteTypeProperty == null || concreteTypeProperty.PropertyType != typeof(Type))
    {
      Assert.Inconclusive("Unable to locate the internal StructureMap.Instance.ConcreteType property");
    }
    var propertyValue = concreteTypeProperty.GetValue(instance, new object[] {}) as Type;

    return typeof (T) == propertyValue;
  }
}

Testing against an internal property is never desirable, but in the case of testing registry's it's been the best approach I've found. The extension method tries to be just smart enough to be able to make tests which rely on it inconclusive if the internal API changes.

Olivas answered 17/10, 2012 at 15:40 Comment(1)
What version of structure map is var pluginGraph = registry.Build(); in? I don't have that option.. I am using version <package id="structuremap" version="3.1.6.186" targetFramework="net451" />Lennalennard
D
2

Check this interesting atircle http://lostechies.com/jimmybogard/2010/01/22/advanced-structuremap-diagnosing-problems/ for example :

[Test]
public void Should_connect_delete_handler_by_registry() 
{
     var container = new Container(new HandlerRegistry());
     var handler = container.GetInstance<IHandler<DeleteEntityCommand<Customer>>>();
     handler.ShouldBeInstanceOf<DeleteEntityCommandHandler<Customer>>(); 
}
Decapolis answered 6/10, 2014 at 13:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.