我正在尝试使用AutoFixture(3.50.6)生成一些ApiController(WebAPI 2)的子类。
我自定义AF以允许使用this customization生成ApiControllers。
由于需要进一步定制,我想创建一个SpecimenBuilder
来创建任何类型的ApiController并使用简单的
fixture.Create<DummyController>();
我尝试过这个测试(NUnit 3):
[TestFixture]
public class ApiControllerSpecimenBuilderTests
{
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization());
fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
}
public class ApiControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Inject(new UriScheme("http"));
fixture.Customize<HttpConfiguration>(c => c
.OmitAutoProperties());
fixture.Customize<HttpRequestMessage>(c => c
.Do(x =>
x.Properties.Add(
HttpPropertyKeys.HttpConfigurationKey,
fixture.Create<HttpConfiguration>())));
fixture.Customize<HttpRequestContext>(c => c
.Without(x => x.ClientCertificate));
}
}
public class ApiControllerSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || !typeof(ApiController).IsAssignableFrom(t))
{
return new NoSpecimen();
}
var controller = context.Resolve(t) as ApiController;
// ...
return controller;
}
}
public class DummyController : ApiController
{
}
失败并出现以下错误:
Ploeh.AutoFixture.ObjectCreationException:AutoFixture无法执行 创建一个System.RuntimeType类型的实例,因为遍历了 对象图包含循环引用。 [...]
路径:Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController - &GT; Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController
为什么DummyController会引用自己的类型?
此外,如果我使用DummyController的空自定义更改测试,它会传递:
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization())
.Customize(new DummyControllerCustomization()); // new customization
fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
public class DummyControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<DummyController>(c => c);
}
}
在这种情况下,使用DummyController类型似乎不再使用SpecimenBuilder。这个空的自定义会使测试通过什么?它是否会覆盖样品制造商?但是为什么不抛出同样的例外,因为我不告诉他省略任何东西(无论如何,我不知道该怎么做才能省略......)?
我想我可以使用OmitOnRecursionBehavior
,但是我想保留默认行为以避免在所有其他情况下递归,而且我更愿意了解发生了什么(或者我是否确实笨)。
答案 0 :(得分:1)
只需删除ApiControllerSpecimenBuilder
:
[TestFixture]
public class ApiControllerSpecimenBuilderTests
{
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization());
//fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
}
上述版本的测试通过(在我的机器上)。
问题是如果ApiControllerSpecimenBuilder
通过了初始的Guard子句,var controller = context.Resolve(t) as ApiController;
会进入无限递归:
context.Resolve(t)
对ISpecimenBuilder
的调用进入新的对象创建'会话'。 AutoFixture会询问其树中的每个t
是否可以处理ApiControllerSpecimenBuilder
的请求。当它达到context.Resolve(t)
时,它会再次致电ApiController
进行回复,依此类推。
您不需要自己完成任何工作,因为AutoFixture已经完全能够为您创建ApiControllerCustomization
个实例(只要ApiController
到位)。
但是,如果我正确理解了整个用例,那么实际的要求是,在AutoFixture为您创建对象之后,您希望对Postprocessor
实例进行某种后处理。 / p>
这种情况的一般解决方案是使用Postprocessor<T>
或<br>
,但有时可能会涉及到正确。通常,有更简单的方法可以实现您想要做的事情。
如果您需要帮助,请提出其他问题。您下次不需要提供赏金,因为我通常会监控 autofixture 标记。这个问题不知何故引起了我的注意;对不起!