我正在尝试使用 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?
最佳答案
根据部分信息,很难确切地说出如何进一步减少上述测试,但我猜测它可以减少。
首先,调用 Inject
和 CreateAnonymous
的组合相当惯用 - 特别是如果您颠倒顺序的话。这称为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/