在AutoFixture如何设置比较复杂(IoC容器等)报名 [英] How to setup more complicated (IoC like) registration in AutoFixture
问题描述
是否有可能使用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屋!