在AutoFixture如何设置比较复杂(IoC容器等)报名 [英] How to setup more complicated (IoC like) registration in AutoFixture

查看:214
本文介绍了在AutoFixture如何设置比较复杂(IoC容器等)报名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能使用AutoFixture时重用生产IoC容器注册在集成测试?

Is it possible to reuse production IoC container registration in integration tests when using AutoFixture?

的问题是,我需要以下灯具的设置,如果依赖性注入嘲笑未注册并注入真正的数据库相关的依赖性

The problem is that I need the following fixture setup to inject mocks if dependency is not registered and inject "real" database related dependencies

var fixture = new Fixture().WithMocks().WithRealDatabase()

我试过

internal static Fixture WithMocks(this Fixture fixture)
{
    fixture.Customize(new AutoMoqCustomization());
}

internal static Fixture WithRealDatabase(this Fixture fixture)
{
    var containerBuilder = new Autofac.ContainerBuilder();
    ...
    containerBuilder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
    containerBuilder.RegisterGeneric(typeof(Repository<>)).AsImplementedInterfaces()        
    containerBuilder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
        .Where(t => t.Name.EndsWith("Repository"))
        .AsImplementedInterfaces();
    ...
    fixture.Customizations.Add(new ContainerSpecimenBuilder(containerBuilder.Build()));
}

internal class ContainerSpecimenBuilder : ISpecimenBuilder
{
    private readonly IContainer container;

    public ContainerSpecimenBuilder(IContainer container)
    {
        this.container = container;
    }

    public object Create(object request, ISpecimenContext context)
    {
        var seededRequest = request as SeededRequest;

        if (seededRequest == null)
        {
            return new NoSpecimen(request);
        }

        var result = this.container.ResolveOptional(seededRequest.Request as Type);
        return result ?? new NoSpecimen(request);
    }
}



但是这种方法的问题是, container.Resolve 不会考虑到已注册的依赖关系AutoFixture。

But the problem with this approach is that container.Resolve will not take into account already registered dependencies in AutoFixture.

是否有任何替代解决这个问题有更复杂的注册?

Is there any alternative to solve this problem to have more complicated registrations?

推荐答案

一般的方法看起来无害,但你应该添加 ContainerSpecimenBuilder ResidueCollectors 的而不是自定义

The general approach looks sound, but you should add the ContainerSpecimenBuilder to ResidueCollectors instead of to Customizations:

fixture.ResidueCollectors.Add(new ContainerSpecimenBuilder(containerBuilder.Build()));



AutoMoqCustomization 还增加了一个节点 ResidueCollectors ,所以你可能需要做一些试验的具体顺序搞清楚究竟是如何使其行为像你想它的行为。 排序问题的。

AutoMoqCustomization also adds a node to ResidueCollectors, so you may need to experiment a bit with the specific ordering to figure out exactly how to make it behave like you want it to behave. The ordering matters.

有关自定义之间的区别的更多信息 ResidueCollectors ,看到的 AutoFixture架构文档

一个稍微简单一些(和更安全?)实施 ContainerSpecimenBuilder 的可能只是处理请求对键入情况下直接,而不是为 SeededRequest ,因为几乎所有的 SeededRequest 值被传递到请求键入对象反正:

A slightly simpler (and safer?) implementation of ContainerSpecimenBuilder could be just handling requests for Type instances directly, instead of for SeededRequest, as almost all SeededRequest values are relayed to requests for Type objects anyway:

internal class ContainerSpecimenBuilder : ISpecimenBuilder
{
    private readonly IContainer container;

    public ContainerSpecimenBuilder(IContainer container)
    {
        this.container = container;
    }

    public object Create(object request, ISpecimenContext context)
    {
        var t = request as Type;

        if (t == null)
            return new NoSpecimen(request);

        var result = this.container.ResolveOptional(t);
        return result ?? new NoSpecimen(request);
    }
}

这篇关于在AutoFixture如何设置比较复杂(IoC容器等)报名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆