C# StructureMap:如何对注册表类进行单元测试?
我有这样一个注册表类:C# StructureMap:如何对注册表类进行单元测试?,c#,.net,structuremap,C#,.net,Structuremap,我有这样一个注册表类: public class StructureMapRegistry : Registry { public StructureMapRegistry() { For<IDateTimeProvider>().Singleton().Use<DateTimeProviderReturningDateTimeNow>(); } 如何验证注册表是否符合我的期望?注意:我之所以引入容器,是因为我在Registry类
public class StructureMapRegistry : Registry
{
public StructureMapRegistry()
{
For<IDateTimeProvider>().Singleton().Use<DateTimeProviderReturningDateTimeNow>();
}
如何验证注册表是否符合我的期望?注意:我之所以引入容器,是因为我在Registry类上没有看到任何可用的验证方法。理想情况下,我希望直接在registry类上进行测试。将registry类想象成一个配置文件——单独测试它并没有什么意义,但您可能希望测试另一个类如何响应它。在本例中,您将测试给定注册表时容器的行为,因此通过将容器引入测试,您走上了正确的道路
在测试中,您可以请求IDateTimeProvider并断言返回的具体类型是您期望的类型。您还可以从容器中检索2个实例,并断言它们是相同的实例(ReferenceEquals),以验证单例行为。在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;
}
}
公共接口IFoo{}
公共类SomeFoo:IFoo{}
公共类注册表:注册表
{
公共食物注册处()
{
For().Use();
}
}
[测试夹具]
公共类FooRegistryTests
{
[测试]
public void ForIFoo\u UseSomeFoo\u AsDefaultInstance()
{
//安排
var registry=new FooRegistry();
//表演
var pluginGraph=registry.Build();
var iFooPluginFamily=pluginGraph.findffamily(typeof(IFoo));
var defaultInstance=iFooPluginFamily.GetDefaultInstance();
//断言
IsTrue(defaultInstance.UsesConcreteType());
}
}
公共静态类TestExtensions
{
公共静态bool UsesConcreteType(此实例)
{
var concreteTypeProperty=typeof(Instance.GetProperty(“ConcreteType”,BindingFlags.Instance | BindingFlags.NonPublic);
如果(concreteTypeProperty==null | | concreteTypeProperty.PropertyType!=typeof(Type))
{
Assert.Inconclusive(“无法找到内部StructureMap.Instance.ConcreteType属性”);
}
var propertyValue=concreteTypeProperty.GetValue(实例,新对象[]{})作为类型;
返回类型(T)=属性值;
}
}
针对内部属性进行测试从来都不可取,但在测试注册表的情况下,这是我发现的最好的方法。如果内部API发生变化,扩展方法试图变得足够聪明,以便能够使依赖它的测试变得不确定。检查这个有趣的循环,例如:
[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>>();
}
[测试]
public void应通过注册表()连接\u删除\u处理程序\u
{
var container=new container(new handleregistry());
var handler=container.GetInstance();
handler.shouldbeininstanceof();
}
这只是对nunit的重写。“ThenAttribute”继承自“TestAttribute”,该场景是一个抽象的TextFixture,具有给定的方法,在[SetUp]中执行时,结构映射的版本是var pluginGraph=registry.Build();在里面我没有这个选择。。我正在使用的版本
[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>>();
}