c# - 使用 AutoFixture 对 Html 助手进行单元测试

标签 c# unit-testing model-view-controller autofixture

我正在尝试使用 AutoFixture 对 Html Helper 进行单元测试。下面是我的 SUT

public static MvcHtmlString SampleTable(this HtmlHelper helper,
    SampleModel model, IDictionary<string, object> htmlAttributes)
{
    if (helper == null)
    {
        throw new ArgumentNullException("helper");
    }
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }

    TagBuilder tagBuilder = new TagBuilder("table");
    tagBuilder.MergeAttributes(htmlAttributes);
    tagBuilder.GenerateId(helper.ViewContext.HttpContext.Items[Keys.SomeKey].ToString());
    return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
}

正如您所看到的,它只返回一个 MVC Html 字符串,其中带有表标签和附加的 Id。 (参见下面的单元测试结果示例)

使用 AutoFixture 进行单元测试:

[Fact]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
{
    var fixture = new Fixture();

    //Arrange
    fixture.Inject<HttpContextBase>(new FakeHttpContext());
    var httpContext = fixture.CreateAnonymous<HttpContextBase>();
    fixture.Inject<ViewContext>(new ViewContext());
    var vc = fixture.CreateAnonymous<ViewContext>();

    vc.HttpContext = httpContext;
    vc.HttpContext.Items.Add(Keys.SomeKey, "foo");

    fixture.Inject<IViewDataContainer>(new FakeViewDataContainer());
    var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
    var sampleModel = fixture.CreateAnonymous<SampleModel>();

    //Act
    var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();

    //Assert
    Assert.Equal("<table id=\"foo\"></table>", result);
}      

FakeHttpContext 和 FakeViewDataContainer 只是 HttpContextBase 和 IViewDataContainer 的假实现。

此测试通过并返回预期结果。然而,我不确定我是否正确使用了 Autofixture。是否有更好的方法在此单元测试中使用 AutoFixture?

最佳答案

根据部分信息,很难确切地说出如何进一步减少上述测试,但我猜测它可以减少。

首先,调用 InjectCreateAnonymous 的组合相当惯用 - 特别是如果您颠倒顺序的话。这称为Freezing匿名值(相当于 DI 容器的 Singleton 生命周期范围)。可以更简洁地表述如下:

var vc = fixture.Freeze<ViewContext>();

测试似乎也将 HttpContext 映射到 FakeHttpContext。 Mapping can be done a little bit easier ,但这会映射 Transient 实例...

无论如何,除非您有令人信服的理由使用 Manual Mocks instead of a dynamic Mock library ,您不妨决定使用 AutoFixture as an auto-mocking container 。这可能会让你摆脱很多这种类型的映射。

因此,考虑到所有这些,我猜测您可能可以将测试简化为如下所示:

[Fact]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());

    //Arrange
    var vc = fixture.Freeze<ViewContext>();
    vc.HttpContext.Items.Add(Keys.SomeKey, "foo");

    var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
    var sampleModel = fixture.CreateAnonymous<SampleModel>();

    //Act
    var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();

    //Assert
    Assert.Equal("<table id=\"foo\"></table>", result);
}

但是,大部分 Arrange 部分现在纯粹是声明性的,并且由于您似乎已经在使用 xUnit.net,因此您可以使用 AutoData Theories for AutoFixture将大部分变量移至方法参数:

[Theory, AutoMoqData]
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml(
    [Frozen]ViewContext vc,
    HtmlHelper htmlHelper,
    SampleModel sampleModel)
{
    //Arrange
    vc.HttpContext.Items.Add(Keys.SomeKey, "foo");

    //Act
    var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();

    //Assert
    Assert.Equal("<table id=\"foo\"></table>", result);
}

这假设您已将 AutoMoqCustomization 与 AutoDataAttribute 桥接起来,如下所示:

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute :
        base(new Fixture().Customize(new AutoMoqCustomization()))
    { }
}

请记住,您可能需要稍微调整上面的代码以使其适合您的 API 的详细信息。这只是一个草图。

关于c# - 使用 AutoFixture 对 Html 助手进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7320449/

相关文章:

c# - 测试 Web.Api ActionFilter 时模拟 HttpActionContext.ActionArguments

objective-c - 测试一个已经重构的方法(拆分成多个方法)?

silverlight - MVC模式什么时候合适?

c# - 如何修复 HTTP 错误 500.22 - 内部服务器错误检测到不适用于集成托管管道模式的 ASP.NET 设置

asp.net - 在 ASP.net core 中,如何在返回 View 时重新加载 _layout 页面()

c# - 如何以编程方式获取 Excel 支持的最早日期

c# - 使用 linq 与 xmlDocument 从 XML 字符串中提取数据

c# - 从处理程序将数据集返回给 ajax

c# - 从一个列表中取出一个随机项目并将其添加到另一个列表

python - Django 中的基本测试