How to configure more complex (IoC like) registration in AutoFixture

Can I reuse IoC container registration in integration tests when using AutoFixture?

The problem is that I need the following instrument setup in order to incase mocks if the dependency is not registered and does not introduce "real" database dependencies

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

The solution I 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 an alternative to solve this problem for more complex registrations?

+3
source share
1 answer

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

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

AutoMoqCustomization also adds a node to ResidueCollectors , so you may need to experiment a bit with a specific order to figure out how to make it behave the way you want it to behave. Order Issues .

See the AutoFixture Architecture documentation for more information on the differences between Customizations and ResidueCollectors .


A slightly simpler (and safer?) Implementation of ContainerSpecimenBuilder can simply process requests for Type instances directly, and not for SeededRequest , since almost all SeededRequest values ​​are passed 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); } } 
+2
source

Source: https://habr.com/ru/post/1235846/


All Articles