We have MVC4 project with Entity Framework for storage. For our tests we recently started using Autofixture and it is really awesome.
Our models graph is very deep and usually creating one object by AutoFixture creates the whole graph: Person -> Team -> Departments -> Company -> Contracts -> .... etc.
The problem with this is time. Object creation takes up to one second. And this leads to slow tests.
What I find myself doing a lot is things like this:
var contract = fixture.Build<PersonContract>()
.Without(c => c.Person)
.Without(c => c.PersonContractTemplate)
.Without(c => c.Occupation)
.Without(c => c.EmploymentCompany)
.Create<PersonContract>();
And this works and it is quick. But this over-specification makes tests hard to read and sometimes I loose the important details like .With(c => c.PersonId, 42)
in the list of unimportant .Without()
.
All these ignored objects are navigational properties for Entity Framework and all are virtual.
Is there a global way to tell AutoFixture to ignore virtual members?
I have tried creating ISpecimentBuilder
, but no luck:
public class IgnoreVirtualMembers : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request.GetType().IsVirtual // ?? this does not exist )
{
return null;
}
}
}
I can't seem to find a way in ISpecimenBuilder
to detect that object we are constructing is a virtual member in another class. Probably ISpecimenBuilder
this is not the right place to do this. Any other ideas?
Read a bit more on Mark's blog (this particularly) I found the way to do what I want:
/// <summary>
/// Customisation to ignore the virtual members in the class - helps ignoring the navigational
/// properties and makes it quicker to generate objects when you don't care about these
/// </summary>
public class IgnoreVirtualMembers : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var pi = request as PropertyInfo;
if (pi == null)
{
return new NoSpecimen(request);
}
if (pi.GetGetMethod().IsVirtual)
{
return null;
}
return new NoSpecimen(request);
}
}
And you can wrap these into customisation:
public class IgnoreVirtualMembersCustomisation : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembers());
}
}
So in your test you just do:
var fixture = new Fixture().Customize(new IgnoreVirtualMembersCustomisation());
and go create your complex models.
Enjoy!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With