需要为ApiControllers创建约定

时间:2013-12-20 22:07:03

标签: c# autofixture

我在测试中有一套工作命令性代码,我试图将其归结为一个基本的测试约定。

我的测试如下:

[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&lt;&gt;()。omit()。with(config).with(request),它会关闭构建这些实例所需的automoq自定义。

其次,这仅适用于SiteVersionController。我更倾向于对我的所有ApiControllers进行概括(也许这是个坏主意,但在我尝试之前我不会知道)。

基本上我的约定如下: 对于所有ApiControllers,创建它们时没有自动属性,但确实将http配置和请求消息属性设置为默认的非空值

1 个答案:

答案 0 :(得分:7)

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

由于自动属性默认情况下处于启用状态,因此会将HttpRequestMessage的相应实例分配给ApiController.Request。加上Auto-mocking自定义,Fixture现在可以创建所有ApiController类的实例。

Web API 2

使用ASP.NET Web API 2(5.0.0.0),事情有点复杂,但经过一些试验和错误,我得到了这个Customization来通过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);
}