![](/img/trans.png)
[英]How to unit test open generic decorator chains in SimpleInjector 2.6.1+
[英]How to unit test decorator registrations using SimpleInjector 3+?
在这里跟进一个较旧的问题 。 说我有以下注册:
container.Register(typeof(IHandleCommand<>), _handlerAssemblies, Lifestyle.Transient);
container.RegisterDecorator(typeof(IHandleCommand<>),
typeof(MetricsCommandHandlerWrapper<>), Lifestyle.Singleton);
MetricsCommandHandlerWrapper
的定义如下:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T> where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory)
{
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public async Task HandleAsync(T command)
{
// code to record metrics around command handling which eventually invokes
await _handlerFactory().HandleAsync(command).ConfigureAwait(false);
}
}
如何编写一个单元测试来断言实际的decoratee处理程序是否已经注册了Transient
生活方式?
我已经尝试编写根并检查注册的闭合IHandleCommand<FakeCommand>
类型,它按预期显示了MetricsCommandHandlerWrapper<FakeCommand>
的ImplementationType
。 在该注册上调用GetRelationships()
会显示其2个依赖项ICollectMetrics
和我感兴趣的依赖项Func<IHandleCommand<FakeCommand>>
工厂委托,它被注册为Singleton
。 但是,在该工厂委托上调用.Dependency.GetInstance()
会抛出实例生成器返回null的异常。
有没有办法断言内部decoratee注册为Transient
,如果是,如何?
使用Func<T>
延迟了对象图的构建,并且从诊断系统的角度来看,图表在那时停止。 因此,不可能进行此分析。
但是,您可以选择在应用程序中进行一些小的更改以允许测试装饰器,而不是完全依赖于Simple Injector的内部。
你可以做的是在装饰器上实现IDecorator
抽象:
public interface IDecorator {
object Decoratee { get; }
}
现在每个装饰器都可以实现这个接口。 对于MetricsCommandHandlerWrapper<T>
,它可能如下所示:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T>, IDecorator where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory) {
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public object Decoratee { get { return _handlerFactory(); }
public async Task HandleAsync(T command) { ... }
}
在IDecorator
接口之上,您可以定义一个简单的扩展方法:
public static IEnumerable<Type> GetDecoratorChain(this IDecorator decorator) {
while (decorator != null) {
yield return decorator.GetType();
decorator = decorator.Decoratee as IDecorator;
}
}
在单元测试中,您现在可以解析处理程序并询问应用装饰器的列表。 使用此列表,您可以验证装饰器是否以正确的顺序应用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.