其他分享
首页 > 其他分享> > CodeGo.net>如何使用SimpleInjector 3单元测试装饰器注册?

CodeGo.net>如何使用SimpleInjector 3单元测试装饰器注册?

作者:互联网

在这里跟进an older question.假设我的注册如下:

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

我该如何编写一个单元测试来断言实际的装饰者处理程序已在Transient生活方式中注册?

我试过组成根并检查封闭的IHandleCommand< FakeCommand>的注册.类型,该类型揭示MetricsCommandHandlerWrapper< FakeCommand>的ImplementationType.如预期的那样.在该注册上调用GetRelationships()会显示其2个依赖项ICollectMetrics和我感兴趣的2个依赖项Func< IHandleCommand< FakeCommand>>.工厂代表,已注册为Singleton.但是,对该工厂委托调用.Dependency.GetInstance()会引发异常,实例生产者返回null.

有什么方法可以断言内部装饰对象已注册为瞬态,如果是,则如何?

解决方法:

Func< T>的使用延迟了对象图的构建,并且从诊断系统的角度来看,图在该点停止.因此,不可能进行此分析.

但是,您可以选择在应用程序中进行一些小的更改以允许测试装饰器,而不是完全依赖Simple Injector的内部结构.

您可以做的是在装饰器上实现IDecorator抽象:

public interface IDecorator {
    object Decoratee { get; }
}

现在,每个装饰器都可以实现此接口.对于MetricsCommandHandlerWrapper< T&gt ;,它可能如下所示:

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

现在,在单元测试中,您可以解析一个处理程序并询问所应用装饰器的列表.使用此列表,您可以验证是否以正确的顺序应用了装饰器.

标签:unit-testing,decorator,c,simple-injector
来源: https://codeday.me/bug/20191119/2035459.html