Модульное тестирование Html Helper с автофиксом

2

Я пытаюсь использовать Unit Test Html Helper с помощью AutoFixture. Ниже мой 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 с табличными тегами и идентификатором, прикрепленным к ней. (Ниже приведен пример Unit Test)

Unit Test с автоскруткой:

[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.

Этот тест проходит и возвращает ожидаемый результат. Тем не менее, я не уверен, что Im правильно использовал Autofixture здесь. Есть ли лучший способ использовать AutoFixture в этом Unit Test?

Теги:
model-view-controller
unit-testing
autofixture

1 ответ

5
Лучший ответ

Основываясь на частичной информации, трудно точно сказать, как можно было бы уменьшить приведенный выше тест, но я бы предположил, что его можно было бы уменьшить.

Прежде всего, комбинация вызова Inject, за которой следует CreateAnonymous, скорее идиоматична, особенно если вы отмените последовательность. Это называется "Замерзание" анонимного значения (и эквивалентно размеру жизненного цикла Single-контейнера DI). Это может быть сказано более кратко:

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

Также кажется, что тест сопоставляет HttpContext с FakeHttpContext. Сопоставление может быть сделано немного проще, но это будет отображать временные экземпляры...

В любом случае, если у вас нет веских причин использовать Manual Mocks вместо динамической библиотеки Mock, вы также можете решить использовать AutoFixture в качестве самонаводящегося контейнера. Это может избавить вас от большого количества картирования этого типа.

Итак, учитывая все это, я бы предположил, что вы могли бы свести тест к чему-то вроде этого:

[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. Это означает только эскиз.

  • 0
    Очень хорошо. Большое спасибо, Марк.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню