Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore virtual properties

Tags:

c#

autofixture

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?

like image 207
trailmax Avatar asked Mar 29 '13 15:03

trailmax


1 Answers

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!

like image 144
trailmax Avatar answered Oct 28 '22 20:10

trailmax