Некоторое время я пытался написать модульный тест для UserViewControl в ASP.NET MVC. Я хотел бы получить код, который выглядит примерно так:
[TestMethod]
public void HaveControlToDisplayThings()
{
var listControl = new ControlUnderTest();
var viewData = new ViewDataDictionary<IList<string>>(this.repo.GetMeSomeData());
// Set up a ViewContext using Moq.
listControl.SetFakeViewContext(viewData);
listControl.ViewData = viewData;
listControl.RenderView(listControl.ViewContext);
// Never got this far, no idea if this will work :)
string s = listControl.ViewContext.HttpContext.Response.Output.ToString();
Assert.AreNotEqual(0, s.Length);
foreach (var item in this.repo.GetMeSomeData())
{
Assert.IsTrue(s.IndexOf(item) != -1);
}
}
К сожалению, что бы я ни пытался, я получаю ошибки изнутри RenderView. Это вызвано (насколько я могу судить) тем, что статический объект HttpContext.Current бесполезен - я получаю NullReferenceException от System.Web.UI.Page.SetIntrinsics.
Я попытался использовать HttpSimulator Фила Хаака, который дал мне объект HttpContext, но обнаружил, что мне также нужно указать поддельный объект HttpBrowserCapabilities, чтобы продвинуться немного дальше:
Subtext.TestLibrary.HttpSimulator simulator = new HttpSimulator();
simulator.SimulateRequest();
var browserMock = new Mock<HttpBrowserCapabilities>();
browserMock.Expect(b => b.PreferredRenderingMime).Returns("text/html");
browserMock.Expect(b => b.PreferredResponseEncoding).Returns("UTF-8");
browserMock.Expect(b => b.PreferredRequestEncoding).Returns("UTF-8");
HttpContext.Current.Request.Browser = browserMock.Object;
Теперь я получаю исключения при доступе к свойствам этого объекта. Я издевался над всеми, кого мог, но, похоже, быстро никуда не ушел.
Кому-нибудь удалось заставить эту работу?
Да, в общем, я не хочу тестировать свои представления, но когда я использую пользовательский элемент управления, это многократно используемый элемент, который часто используется во всем приложении и не имеет кода контроллера, о котором можно было бы говорить. Я хочу проверить, что он может быть создан и визуализирован и содержит примерно то, что нужно.
Насколько я понимаю, вы на самом деле тестируете repo.GetMeSomeData (), который немного не зависит от представления или управления пользователем. Можете ли вы просто проверить, дает ли repo.GetMeSomeData () то, что вы хотите, и не вызывает ли элемент управления?
Привет, я знаю, что GetMeSomeData работает, поскольку тестируется независимо, я пытаюсь проверить, что данные этого вызова отображаются в HTML.





Один из вариантов - запускать модульные тесты внутри браузера. Для таких случаев у меня был успех с Селен.
Мы отказались от представлений модульного тестирования и теперь используем браузерные тесты WatiN как часть нашей сборки.
Мы также используем Resharper Solution Wide Analysis, чтобы проверить наличие ошибок компилятора. Не идеально, но дает очень похожие результаты. Оборотная сторона - тесты WatiN проходят медленно.
К сожалению, средство просмотра ASP.NET использует VirtualPathProvider в среде размещения ASP.NET. Что еще хуже, я отследил другой код с помощью Reflector и обнаружил, что есть и другие зависимости от некоторых ссылок жесткого кода на утилиты VirtualPath. Я надеюсь, что они исправят это в выпуске, чтобы мы могли по-настоящему протестировать наши представления и то, как они отображаются.
Принимая это как ответ, потому что кажется, что это по существу: Нет, нет способа модульный тест результата рендеринга представлений. Использование селена, ватина или его эквивалента - хорошая альтернатива, но это не то, чем я действительно хочу заниматься - тестирование вывода управления / просмотра без использования браузера.
Это значения, которые необходимо установить в объекте HttpBrowserCapabilities для запуска сайта веб-форм asp.net, я бы попытался убедиться, что они установлены, и посмотреть, решит ли это вашу проблему, я не уверен, что это так, но эй стоит попробовать?
Надеюсь это поможет.
Спасибо, я попробую в следующий раз, когда буду работать над этим кодом.
Я бы порекомендовал селен также для тестирования пользовательского интерфейса. В стандартном приложении MVC есть немало вещей, которые можно тестировать по модулю, но компоненты уровня пользовательского интерфейса всегда казались более подходящими для тестирования в браузере, такого как Selenium. Вы можете интегрировать тестирование Selenium со своим модульным тестированием, используя cruisecontrol.net.
Вот гид для интеграции Selenium с вашим CC.Net.
Используйте TypeMock, чтобы высмеять зависимости. Я написал одно сообщение в блоге о том, как имитировать зависимости запроса и ответа на уровне контроллера. Может быть, это поможет.
Я давно отказался от модульного тестирования представления. Попробуйте переместить любую имеющуюся бизнес-логику в контроллеры и вместо этого протестируйте их. Представления, как известно, сложны для модульного тестирования. Это может быть реальный ответ, но я отказался от него некоторое время назад, потому что наши взгляды меняются слишком быстро.