Хорошо, поэтому я использую MVCContrib TestHelper для модульного тестирования моих контроллеров, что прекрасно работает.
Хотя, как и многие другие, под модульным тестом я действительно имею в виду интеграционный тест, и я хочу, по крайней мере, убедиться, что мои представления отображаются без ошибок, учитывая предоставленную модель ... в противном случае я могу пропустить целый класс ошибок, в основном связанных с модель, хотя я тестирую контроллер (например, представление не рендерится, если свойство модели имеет значение null).
Во всяком случае, я начал пытаться выяснить, как это сделать (иначе поискать, как это сделать). Казалось, что самым простым способом было создать HTMLHelper и сделать так, чтобы он просто отображал представления (частично в этом случае).
К сожалению, когда я пытаюсь использовать мой поддельный HTMLHelper, он жалуется, что в данных маршрута нет имени контроллера.
Конечно, я смотрю и контроллеры RouteData не заполнены. К сожалению, RouteData.Values RouteValueDictionary доступен только для чтения, поэтому я не могу просто предоставить необходимые значения.
Я не женат на идее HTMLHelper, чтобы решить проблему фактического рендеринга представления как части теста, так что не стесняйтесь предлагать альтернативы там, но, пожалуйста, не предлагайте мне протестировать свои виды с использованием Selenium, Watin или другие инструменты тестирования пользовательского интерфейса ... Я хочу, чтобы элемент управления мог выполнять такие действия, как манипулирование и восстановление состояния и информации о данных для некоторых тестов, чего я не могу сделать с тестированием на основе пользовательского интерфейса.
Вот код, который я сейчас использую для рендеринга частичного:
public class FakeView : IView
{
#region IView Members
public void Render(ViewContext viewContext, System.IO.TextWriter writer)
{
throw new NotImplementedException();
}
#endregion
}
public class WebTestUtilities
{
public static void prepareCache()
{
SeedDataManager seed = new SeedDataManager();
seed.CheckSeedDataStatus();
}
public static string RenderRazorViewToString(string viewName, object model, Controller controller)
{
var sb = new StringBuilder();
var memWriter = new StringWriter(sb);
var html = new HtmlHelper(new ViewContext(controller.ControllerContext,
new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), memWriter),
new ViewPage());
//This fails because it can't extract route information like the controller name)
html.RenderPartial(viewName, model);
return sb.ToString();
}
public void setupTestEnvironment(Controller controller)
{
RouteTable.Routes.Clear();
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Main", action = "DefaultView", id = UrlParameter.Optional }
);
ModelBinders.Binders[typeof(DateTime)] = new DateTimeModelBinder();
ModelBinders.Binders[typeof(DateTime?)] = new DateTimeModelBinder();
ModelMetadataProviders.Current = new DateTimeMetadataProvider();
}
}
А вот мой метод испытаний:
[TestMethod]
public void GetUserTableView()
{
ViewResult result = controller.UserTable() as ViewResult;
//I can populate the route and handler on the controller...
RouteData routes = RouteTable.Routes.GetRouteData(controller.HttpContext);
controller.RouteData.Route = routes.Route;
controller.RouteData.RouteHandler = routes.RouteHandler;
RouteValueDictionary routeKeys = new RouteValueDictionary();
routeKeys.Add("controller", "UserManagement");
routeKeys.Add("action", "UserTable");
//But the RouteData.Values collection is read only :(
controller.RouteData = new RouteData(){Values = routeKeys};
string renderedView = WebTestUtilities.RenderRazorViewToString(result.ViewName, result.Model, controller);
}
Кстати, конкретная ошибка, которую я получаю:
RouteData должен содержать элемент с именем 'controller' с непустым строковым значением.