Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I apply AutoFixture customizations to anything inheriting from a base class?

In an attempt to DRY up my unit tests, I'm trying to use AutoFixture as an IoC container to instantiate my system under test (SUT), which in this particular case are ASP.NET MVC Controllers. Therefore, I want to customize AutoFixture to create controllers without auto-properties.

I tried adding a customization for ControllerBase, but it doesn't seem to work for subclasses of ControllerBase.

fixture.Customize<ControllerBase>(c => c.OmitAutoProperties());

Here's an example of the test I want to be able to write:

    [Theory, AutoFixtureData]
    public void ControllerTest(AccountController controller) {
        Assert.Equal(default(UrlHelper), controller.Url);
    }

Naturally, it works if I manually add one customization for each specific controller in my project, but who wants to do that? Is there a better way?

like image 626
Brant Bobby Avatar asked Dec 13 '12 22:12

Brant Bobby


1 Answers

The following Customization passes the above test, and does what you seem to ask

public class MvcCostumization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(
            new FilteringSpecimenBuilder(
                new MethodInvoker(new ModestConstructorQuery()),
                new ControllerSpecification()));
    }

    private class ControllerSpecification : IRequestSpecification
    {
        public bool IsSatisfiedBy(object request)
        {
            var t = request as Type;
            if (t == null)
                return false;

            return typeof(ControllerBase).IsAssignableFrom(t);
        }
    }
}

However, that disables all properties of all MVC Controllers, including User, HttpContext, ModelState, Request, Response, etc. You might need those in unit tests, so are you sure you want to do that?

I'll be the first person to agree that the MVC Controller base class is one huge SRP violation, but it's a class which is given to us, so there's nothing we can do about except trying to make the best of it.

Usually, you only need to twist it a little to make AutoFixture fill most of the properties automatically.

In MVC 3 projects, this, combined with the AutoMoq extension, is sufficient to create Controller instances:

fixture.Customize<ModelBindingContext>(c => c
    .Without(x => x.Model)
    .Without(x => x.ModelType));
fixture.Inject(CultureInfo.CurrentCulture);
like image 195
Mark Seemann Avatar answered Sep 23 '22 09:09

Mark Seemann