我有一个这样的注册表类:
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类上看到任何可用的验证方法。理想情况下,我想直接在注册表类上进行测试。
答案 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>>();
}