StructureMap:我如何单元测试注册表类?

时间:2010-03-18 11:24:21

标签: c# .net structuremap

我有一个这样的注册表类:

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

我想测试配置是否符合我的意图,所以我开始编写测试:

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
    }
}

如何验证注册表是否符合我的期望?注意:我介绍了容器,因为我没有在Registry类上看到任何可用的验证方法。理想情况下,我想直接在注册表类上进行测试。

3 个答案:

答案 0 :(得分:3)

将Registry类视为配置文件 - 单独测试它并不是真的有意义,但您可能想测试另一个类如何响应它。在这种情况下,您将测试Container在给定注册表时的行为方式,因此您可以通过将Container引入测试来处于正确的轨道上。

在测试中,您可以请求IDateTimeProvider并断言返回的具体类型是您期望的类型。您还可以从容器中检索2个实例,并声明它们是相同的实例(ReferenceEquals)以验证单例行为。

答案 1 :(得分:3)

在StructureMap中,注册表用于生成PluginGraph;所以要对注册表进行单元测试,你需要检查它的设计是否产生了正确的图形。不幸的是,测试验证最好针对内部属性进行,这里有一个示例:

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;
  }
}

对内部属性进行测试是不可取的,但在测试注册表的情况下,这是我发现的最佳方法。扩展方法试图足够智能,以便能够在内部API发生变化时进行依赖于它的测试。

答案 2 :(得分:1)

检查这个有趣的atircle http://lostechies.com/jimmybogard/2010/01/22/advanced-structuremap-diagnosing-problems/,例如:

[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>>(); 
}