使用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<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中已注册的依赖项。
是否有其他方法可以解决此问题,以便进行更复杂的注册?
答案 0 :(得分:2)
一般方法看起来很合理,但您应该将ContainerSpecimenBuilder
添加到ResidueCollectors
而不是Customizations
:
fixture.ResidueCollectors.Add(new ContainerSpecimenBuilder(containerBuilder.Build()));
AutoMoqCustomization
还向ResidueCollectors
添加了一个节点,因此您可能需要对特定排序进行一些实验,以确切了解如何使其表现得像您希望它的行为。 The ordering matters
有关Customizations
和ResidueCollectors
之间差异的详细信息,请参阅AutoFixture architecture documentation。
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);
}
}