Autofac - 为单元测试获取已注册的通用设计器。

问题描述 投票:0回答:2

我使用的是Autofac 5.2.0版本,我有多个。Decorators(https:/autofaccn.readthedocs.ioenlatestadvancedadapters-decorators.html。)

我这样注册他们。

containerBuilder.RegisterGenericDecorator(
    typeof(QueryHandlerExceptionDecorator<,>),
    typeof(IQueryHandler<,>));

这样做非常好

注册本身是动态发生的,取决于一个配置文件或一个 Action<ContainerBuilder> 语句。

在我的单元测试中,我想做这样的事情。

Assert.IsTrue(containberBuilder.IsGenericDecoratorRegistered(
    typeof(QueryHandlerExceptionDecorator<,>)));

但无论是 ContainerBuilder 阶级和 IContainer 在调用 containerBuilder.Build(); 提供任何方法或属性来获取装饰者注册。

我看到了下面的文章,有一个自定义注册源。https:/stackoverflow.coma223450451099519。但即使在那里,我也找不到获取注册装饰者列表的方法。

当然,当我得到一个被装饰的实例时,我可以对特定的装饰者提供的一些功能进行单元测试,并假设它是由该实例注册的,但这不是我想做的方式。

c# unit-testing dependency-injection decorator autofac
2个回答
0
投票

由于我无法找出一个合适的解决方案来直接找出哪些装饰符是被配置的,所以我最终采用了我的 "注册器 "的解决方案。

public interface IDecoratorRegistrar
{
    void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType);
    void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType);
    void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType);
    void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType, Func<IDecoratorContext, bool>? condition);
}

这是Autofac注册的实际实现。

public class DecoratorRegistrar : IDecoratorRegistrar
{
    public void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType)
    {
        RegisterGenericDecorator(builder, decoratorType, serviceType, null);
    }
    public void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType, Func<IDecoratorContext, bool>? condition)
    {
        builder.RegisterGenericDecorator(decoratorType, serviceType, condition);
    }
    public void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType)
    {
        RegisterDecorator(builder, decoratorType, serviceType, null);
    }
    public void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType, Func<IDecoratorContext, bool>? condition)
    {
        builder.RegisterDecorator(decoratorType, serviceType, condition);
    }
}

单元测试的实现是:

public class MockDecoratorRegistrar : IDecoratorRegistrar
{
    public IList<(Type decoratorType, Type serviceType)> Decorators { get; } = new List<(Type decoratorType, Type serviceType)>();
    public IList<(Type decoratorType, Type serviceType)> GenericDecorators { get; } = new List<(Type decoratorType, Type serviceType)>();

    public void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType)
    {
        Decorators.Add((decoratorType, serviceType));
    }

    public void RegisterDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType, Func<IDecoratorContext, bool>? condition)
    {
        Decorators.Add((decoratorType, serviceType));
    }

    public void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType)
    {
        GenericDecorators.Add((decoratorType, serviceType));
    }

    public void RegisterGenericDecorator(ContainerBuilder builder, Type decoratorType, Type serviceType, Func<IDecoratorContext, bool>? condition)
    {
        GenericDecorators.Add((decoratorType, serviceType));
    }
}

为了注册一个装饰器,我现在调用:

decoratorRegistrar.RegisterGenericDecorator(containerBuilder, typeof(ActionCommandHandlerExceptionDecorator<>), typeof(IActionCommandHandler<>));

decoratorRegistrar 要么是一个实例 DecoratorRegistrarMockDecoratorRegistrar 在单元测试中。

在我的单元测试中,我现在可以轻松地通过调用来检查注册。

mockDecoratorRegistrar.GenericDecorators.Should().Contain(item => item.decoratorType == expectedType);

这个抽象概念解决了我的实际问题。不过,如果有人有直接从Autofac访问装饰者注册的解决方案,请告诉我。


0
投票

您可以通过使用 IComponentRegistry.DecoratorsFor 的方法。ComponentRegistry 属性的方法。

您可以向该方法传递一个 TypedService 以获得装饰者的注册,像这样。

var decorators = container.ComponentRegistry.DecoratorsFor(new TypedService(typeof(IDecoratedService)));
© www.soinside.com 2019 - 2024. All rights reserved.