vendredi 31 juillet 2015

How to setup more complicated (IoC like) registration in AutoFixture

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()

The solution I've tried

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

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?

Aucun commentaire:

Enregistrer un commentaire