Question

I am using AutoFixture to try to test my controllers for a WebApi site. I am using the AutoData feature with Moq as noted on Ploeh's blog.

My controller takes an IDepartmentManager in the constructor. Here is my test:

[Theory, AutoMoqData]
public void GetCallsManagerCorrectly(
    [Frozen]Mock<IDepartmentManager> departmentManagerMock,
    DepartmentsController sut)
{
    // Fixture setup
    // Exercise system
    sut.Get();
    // Verify outcome
    departmentManagerMock.Verify(d => d.GetAllDepartments(), Times.Exactly(1));
    // Teardown
}

When I run this test it fails with the following:

GetCallsManagerCorrectly has failed:
System.InvalidOperationException : An exception was thrown while getting data for theory Provision.Tests.WebApiControllerTests.DepartmentControllerTests.GetCallsManagerCorrectly: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: Only 'http' and 'https' schemes are allowed. Parameter name: value at System.Net.Http.HttpRequestMessage.set_RequestUri(Uri value)

First of all, is this still a valid and recommended way to write these tests? I love how small it makes everything.

Secondly, what should I do to fix this? If I change my test to this:

[Theory, AutoMoqData]
public void GetCallsManagerCorrectly(
    [Frozen]Mock<IDepartmentManager> departmentManagerMock)
{
    // Fixture setup
    DepartmentsController sut =
        new DepartmentsController(departmentManagerMock.Object);
    // Exercise system
    sut.Get();
    // Verify outcome
    departmentManagerMock.Verify(d => d.GetAllDepartments(), Times.Exactly(1));
    // Teardown
}

it passes, but then I lose the ability to have the controller built up automatically and still be ok if I add parameters to the constructor.

Was it helpful?

Solution

This is definitely the recommended way to write tests with AutoFixture. The issue is pretty easy to fix.

Instead of implementing the [AutoMoqData] attribute as described in the blog post, I'd recommend creating a slightly different attribute and Customization - a set that basically will act as a set of conventions for an entire unit test project. I always do this, and I always go to great lengths to have only a single set of conventions for a single unit test project. A single set of conventions help me keep my tests (and the SUTs) consistent.

public class AutoMyWebApiDataAttribute : AutoDataAttribute
{
    public AutoMyWebApiDataAttribute()
        : base(new Fixture().Customize(new MyWebApiCustomization()))
    {
    }
}

The MyWebApiCustomization could be defined like this:

public class MyWebApiCustomization : CompositeCustomization
{
    public MyWebApiCustomization()
        : base(
            new HttpSchemeCustomization(),
            new AutoMoqCustomization(),
        )
    {
    }

    private class HttpSchemeCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Inject(new UriScheme("http"));
        }
    }
}

Note the additional HttpSchemeCustomization class - that should do the trick.

Please note that the order of Customizations matters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top