如何在AutoFixture中设置更复杂(IoC类似)的注册
使用AutoFixture时,是否可以在集成测试中重用生产IoC容器注册?
问题是,如果未注册依赖项,我需要以下fixture设置来注入模拟并注入“真正的”数据库相关依赖项
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().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中已注册的依赖项。
是否有任何替代方案可以解决此问题,以便进行更复杂的注册?
一般方法看起来很合理,但您应该将ContainerSpecimenBuilder
添加到ResidueCollectors
而不是Customizations
:
fixture.ResidueCollectors.Add(new ContainerSpecimenBuilder(containerBuilder.Build()));
AutoMoqCustomization
还向ResidueCollectors
添加了一个节点,因此您可能需要对特定排序进行一些实验,以确切了解如何使其表现得像您希望它的行为。 订购很重要 。
有关Customizations
和ResidueCollectors
之间区别的更多信息,请参阅AutoFixture体系结构文档 。
ContainerSpecimenBuilder
一个稍微简单(且更安全?)的实现可能只是直接处理Type
实例的请求,而不是SeededRequest
,因为几乎所有的SeededRequest
值都被中继到Type
对象的请求:
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); } }