需要为ApiControllers创建约定。

11

我有一组可工作的命令式代码在测试中,并尝试将其概括为一个必要的测试惯例。

我的测试看起来像下面这样:

[Theory, BasicConventions]
public void GetVersionOnSiteVersionControllerReturnsASiteVersion(IFixture fixture)
{
    fixture.OmitAutoProperties = true;
    SiteVersion expected = fixture.Create<SiteVersion>();
    SiteVersion actual = null;

    var sut = fixture.Create<SiteVersionController>();

    var response = sut
        .GetSiteVersion()
        .ExecuteAsync(new CancellationToken())
        .Result
        .TryGetContentValue<SiteVersion>(out actual);

    actual.AsSource().OfLikeness<SiteVersion>().ShouldEqual(expected);
}

我还有一种自定义方式可以使其正常工作,即通过将HttpConfigurationHttpRequestMessage设置为默认的非空值。

public class ApiControllerCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var origin = fixture.OmitAutoProperties;
        fixture.OmitAutoProperties = true;
        var sut = fixture.Create<SiteVersionController>();
        sut.Configuration = fixture.Create<HttpConfiguration>();
        sut.Request = fixture.Create<HttpRequestMessage>();
        fixture.Inject<SiteVersionController>(sut);
        fixture.OmitAutoProperties = origin;
    }
}

首先,这看起来很丑,但如果我使用Build<>().omit().with(config).with(request),它会关闭需要构建这些实例的automoq自定义设置。

其次,这仅适用于SiteVersionController。我更希望将其推广到所有我的ApiControllers(也许这是个坏主意,但在尝试之前我不会知道)。

本质上,我的约定如下:对于所有的ApiControllers,创建它们时不要使用自动属性,但将http配置和请求消息属性设置为默认的非null值


你正在使用哪种 ApiController 类型?是 ASP.NET Web API 吗?它的版本是什么? - Mark Seemann
1
我的NuGet软件包管理器显示ASP.NET Web API版本5.0.0。 - cocogorilla
1
相关链接:https://dev59.com/O2Ij5IYBdhLWcg3wxnyd - Mark Seemann
1个回答

10
ApiControllers相当难以连接,因为您需要为它们分配某些属性才能使一切正常工作。至少,您需要分配Request属性,否则Controller无法调用Request.CreateResponse。因此,关闭ApiController实例的自动属性不是一个好策略。相反,您可以配置AutoFixture以正确连接HttpRequestMessage实例。 Web API 1 使用ASP.NET Web API 1时,我通常使用这样的自定义设置:
public class WebApiCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customize<HttpRequestMessage>(c => c
            .Do(x =>
                x.Properties.Add(
                    HttpPropertyKeys.HttpConfigurationKey,
                    new HttpConfiguration())));
    }
}

由于自动属性默认开启,这将会为ApiController.Request分配一个相应的 HttpRequestMessage 实例。配合自动模拟容器定制,Fixture现在可以创建所有你的ApiController类的实例。

Web API 2

使用 ASP.NET Web API 2 (5.0.0.0),情况稍微复杂一些,但通过一点点反复试验,我让这个定制通过了808个测试:

public class WebApiCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customize<HttpConfiguration>(c => c
            .OmitAutoProperties());
        fixture.Customize<HttpRequestMessage>(c => c
            .Do(x =>
                x.Properties.Add(
                    HttpPropertyKeys.HttpConfigurationKey,
                    fixture.Create<HttpConfiguration>())));
        fixture.Customize<HttpRequestContext>(c => c
            .Without(x => x.ClientCertificate));
    }
}

约定

如果您将其打包到[AutoData]属性中,您应该能够重构您的测试为:

[Theory, BasicConventions]
public void GetVersionOnSiteVersionControllerReturnsASiteVersion(
    SiteVersionController sut,
    SiteVersion expected)
{
    SiteVersion actual = null;

    var response = sut
        .GetSiteVersion()
        .ExecuteAsync(new CancellationToken())
        .Result
        .TryGetContentValue<SiteVersion>(out actual);

    actual.AsSource().OfLikeness<SiteVersion>().ShouldEqual(expected);
}

1
这太棒了。问题是,谢天谢地,我正在逐渐掌握AutoFixture,我的大部分困惑都在于尝试连接这样的事情。你如何研究这个问题,有什么策略吗?还是只有经验? - cocogorilla
7
好的,个人而言,我编写了AutoFixture,所以你可以说我有点作弊 :) 我也邀请其他人回答这个问题。 - Mark Seemann
1
ASP.NET Web API 2在F#中的相同定制可以在以下链接找到:https://gist.github.com/moodmosaic/2789ba06980880217df7 - Nikos Baxevanis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接