Тестирование HtmlHelpers в ASP.NET MVC

Есть ли способ (модульное) протестировать мои собственные HtmlHelpers? В случае, если я хочу иметь настраиваемый элемент управления (отображаемый с помощью HtmlHelper) и я знаю требования для этого элемента управления, как я могу сначала написать тесты, а затем написать код? Есть ли конкретный (приятный) способ сделать это?

Стоит ли?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
0
7 341
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Основная проблема заключается в том, что вам нужно издеваться над HtmlHelper, потому что вы можете использовать методы помощника для получения маршрутов или значений или возврата результата другого метода расширения. Класс HtmlHelper имеет довольно много свойств, и некоторые из них довольно сложные, такие как ViewContext или текущий контроллер.

Сообщение от Бена Харта, который объясняет, как создать такой макет с помощью Moq. Может быть легко переведен на другой макет фреймворка.

Это моя версия Rhino Mocks, адаптированная к изменениям в MVC Framework. Он не полностью протестирован, но у меня работает, но не ожидайте идеальных результатов:

    public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData)
    {
        var mocks = new MockRepository();

        var cc = mocks.DynamicMock<ControllerContext>(
            mocks.DynamicMock<HttpContextBase>(),
            new RouteData(),
            mocks.DynamicMock<ControllerBase>());

        var mockViewContext = mocks.DynamicMock<ViewContext>(
            cc,
            mocks.DynamicMock<IView>(),
            viewData,
            new TempDataDictionary());

        var mockViewDataContainer = mocks.DynamicMock<IViewDataContainer>();

        mockViewDataContainer.Expect(v => v.ViewData).Return(viewData);

        return new HtmlHelper(mockViewContext, mockViewDataContainer);
    }

к сожалению, сообщения об ошибках в блоге, но приведенное выше довольно хорошо объясняет, что вам нужно делать

MJJames 07.08.2010 22:43

Похоже, они немного изменили структуру MVC, поскольку вышеизложенное, поскольку ViewContext теперь также принимает TextWriter

Rob West 22.12.2010 17:12

Это очень полезно, но при тестировании против MVC3 мне пришлось настроить это, добавив новый параметр в mockViewContextConstructor (я использовал TextWriter.Null), и вместо mockViewDataContainer мне пришлось явно установить ViewData (например, mockViewDataContainer.ViewData = viewData;) или Rhino Mocks выдает исключение. .

Brandon Linton 25.08.2011 01:10

Кто-нибудь тестировал вспомогательный метод, который называется htmlhelper.partial? Все работает до тех пор, пока он не вызовет это, а затем выдаст некоторую ошибку, что-то связанное с необходимостью вернуть что-то обратно с помощью tempdata. Почему они так усложнили тестирование?

nportelli 29.09.2011 00:17

Я создаю собственный помощник, и это код, который я использую для имитации httphelper с помощью Moq и ASP MVC 2. Я также передаю в качестве параметра имитацию HttpRequestBase. Вы можете удалить это, если оно вам не нужно

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData, Mock requestMock)
        {
            var contextBaseMock = new Mock();
            contextBaseMock.SetupGet(cb => cb.Request).Returns(requestMock.Object);

            var cc = new ControllerContext(contextBaseMock.Object,
                                            new RouteData(),
                                            new Mock().Object);
            var vctx = new ViewContext(
                cc,
                new Mock().Object,
                viewData,
                new TempDataDictionary(),
                new HtmlTextWriter(new StreamWriter(new MemoryStream())));

            var mockViewDataContainer = new Mock();

            mockViewDataContainer.SetupGet(v => v.ViewData).Returns(viewData);

            return new HtmlHelper(vctx, mockViewDataContainer.Object);
        }

Если кто-то ищет, как создать HtmlHelper<T> (то, что я искал), вот реализация, которая может помочь - мой тип - это класс с именем Model:

public static HtmlHelper<Model> CreateHtmlHelper()
{
    ViewDataDictionary vd = new ViewDataDictionary(new Model());

    var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object,
                                                  new RouteData(),
                                                  new Mock<ControllerBase>().Object);

    var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object);

    var mockViewDataContainer = new Mock<IViewDataContainer>();
    mockViewDataContainer.Setup(v => v.ViewData).Returns(vd);

    return new HtmlHelper<Model>(viewContext, mockViewDataContainer.Object);
}

Или более общая реализация:

    public HtmlHelper<T> CreateHtmlHelper<T>() where T : new()
    {
        var vd = new ViewDataDictionary(new T());

        var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object,
                                                      new RouteData(),
                                                      new Mock<ControllerBase>().Object);

        var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object);

        var mockViewDataContainer = new Mock<IViewDataContainer>();
        mockViewDataContainer.Setup(v => v.ViewData).Returns(vd);

        return new HtmlHelper<T>(viewContext, mockViewDataContainer.Object);
    }

Другие вопросы по теме