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





Основная проблема заключается в том, что вам нужно издеваться над 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);
}
Похоже, они немного изменили структуру MVC, поскольку вышеизложенное, поскольку ViewContext теперь также принимает TextWriter
Это очень полезно, но при тестировании против MVC3 мне пришлось настроить это, добавив новый параметр в mockViewContextConstructor (я использовал TextWriter.Null), и вместо mockViewDataContainer мне пришлось явно установить ViewData (например, mockViewDataContainer.ViewData = viewData;) или Rhino Mocks выдает исключение. .
Кто-нибудь тестировал вспомогательный метод, который называется htmlhelper.partial? Все работает до тех пор, пока он не вызовет это, а затем выдаст некоторую ошибку, что-то связанное с необходимостью вернуть что-то обратно с помощью tempdata. Почему они так усложнили тестирование?
Я создаю собственный помощник, и это код, который я использую для имитации 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);
}
к сожалению, сообщения об ошибках в блоге, но приведенное выше довольно хорошо объясняет, что вам нужно делать