Autofixture 和 WebApi 控制器

Bri*_*ord 4 unit-testing moq xunit autofixture asp.net-web-api

我正在使用 AutoFixture 尝试为 WebApi 站点测试我的控制器。如Ploeh 的博客所述,我将 AutoData 功能与 Moq 结合使用。

我的控制器在构造函数中使用 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
}
Run Code Online (Sandbox Code Playgroud)

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

GetCallsManagerCorrectly 失败:
System.InvalidOperationException:获取理论数据时抛出异常 Provision.Tests.WebApiControllerTests.DepartmentControllerTests.GetCallsManagerCorrectly:System.Reflection.TargetInvocationException:调用目标已抛出异常。---> System.ArgumentException: 只允许使用“http”和“https”方案。参数名称: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
}
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ann 6

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

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

public class AutoMyWebApiDataAttribute : AutoDataAttribute
{
    public AutoMyWebApiDataAttribute()
        : base(new Fixture().Customize(new MyWebApiCustomization()))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

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"));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意额外的 HttpSchemeCustomization 类 - 这应该可以解决问题。

请注意,定制的顺序很重要