自动混合和WebApi控制器

时间:2012-09-26 16:10:17

标签: unit-testing asp.net-web-api moq xunit autofixture

我正在使用AutoFixture尝试为WebApi站点测试我的控制器。我正在使用Moq的AutoData功能,如Ploeh's blog所述。

我的控制器在构造函数中使用IDepartmentManager。这是我的测试:

[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
}

当我运行此测试时,它失败并显示以下内容:

  

GetCallsManager错误地失败了:
  System.InvalidOperationException:抛出异常时   获取理论数据   Provision.Tests.WebApiControllerTests.DepartmentControllerTests.GetCallsManagerCorrectly:   System.Reflection.TargetInvocationException:抛出了异常   通过调用的目标。 ---&GT; System.ArgumentException:仅   允许'http'和'https'方案。参数名称:值at   System.Net.Http.HttpRequestMessage.set_RequestUri(Uri值)

首先,这仍然是编写这些测试的有效和推荐方法吗?我喜欢它创造的一切都很小。

其次,我该怎么做才能解决这个问题?如果我将测试改为:

[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
}

它通过,但后来我失去了自动构建控制器的能力,如果我向构造函数添加参数仍然可以。

1 个答案:

答案 0 :(得分:4)

这绝对是使用AutoFixture编写测试的推荐方法。这个问题很容易解决。

我不建议实现博客文章中描述的[AutoMoqData]属性,而是建议创建一个稍微不同的属性和自定义 - 一个基本上将作为整个单元测试项目的一组约定的集合。我总是这样做,而且我总是竭尽全力为单个单元测试项目只有一套约定。一组约定可以帮助我保持测试(和SUT)的一致性。

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

MyWebApiCustomization可以像这样定义:

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"));
        }
    }
}

注意额外的HttpSchemeCustomization类 - 应该做的。

请注意the order of Customizations matters