I'm trying to generate some subclasses of ApiController (WebAPI 2) using AutoFixture (3.50.6).
I customized AF to allow generating ApiControllers using this customization.
Because of further customization needs, I'd like to create a SpecimenBuilder
that would create any type of ApiController and apply this configuration with a simple
fixture.Create<DummyController>();
I tried this test (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
{
}
That fails with the following error :
Ploeh.AutoFixture.ObjectCreationException : AutoFixture was unable to create an instance of type System.RuntimeType because the traversed object graph contains a circular reference. [...]
Path: Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController --> Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController
Why does the DummyController have a reference to its own type ?
Moreover, if I change the test with an empty customization for DummyController, it passes :
[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);
}
}
In this case, the SpecimenBuilder seems to not be hit anymore with the DummyController type. What does this empty customization do that makes the test pass ? Does it override the specimen builder ? But then why doesn't it throw the same exception, as I don't tell him to omit anything (and anyway, I wouldn't know what to make it omit...) ?
I guess I could use the OmitOnRecursionBehavior
, but I'd like to keep the default behavior to avoid recursions in all the other cases, plus I'd rather understand what is happening (or if I did smth really stupid).