Модульное тестирование Html Helper с автофиксом - PullRequest
2 голосов
/ 06 сентября 2011

Я пытаюсь провести модульное тестирование 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));
}

Как вы можете видеть, она просто возвращает HTML-строку MVC с тегами таблицы и прикрепленным к ней Id.(См. Пример результатов модульного теста ниже)

Модульный тест с автофиксом:

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

Thisтест проходит и возвращает ожидаемый результат.Тем не менее, я не уверен, что правильно использую автофиксатор здесь.Есть ли лучший способ использовать автокрепление в этом модульном тесте?

1 Ответ

5 голосов
/ 06 сентября 2011

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

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

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

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

В любом случае, если у вас нет веских причин использовать Ручные 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 для 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.Это только эскиз.

...