好的,我正在使用 MVCContrib TestHelper 对我的控制器进行单元测试,效果很好。
不过,像很多人一样,通过单元测试,我真正的意思是这里的集成测试,我想至少确保我的视图在给定提供的模型的情况下呈现没有错误......否则我可能会错过一整类基本上与模型相关的错误,甚至尽管我正在测试控制器(例如,如果模型属性为空,则视图不会呈现)。
不管怎样,我开始尝试弄清楚如何做到这一点(又名谷歌搜索如何做到这一点)。看起来最简单的方法是构造一个 HTMLHelper 并让它只渲染视图(在本例中是部分视图)。
不幸的是,当我尝试使用我的模拟 HTMLHelper 时,它抱怨路由数据中没有可用的控制器名称。
果然,我看到控制器的 RouteData 没有填充。不幸的是 RouteData.Values RouteValueDictionary 是只读的,所以我不能只提供必要的值。
我并没有接受 HTMLHelper 的想法来解决作为测试一部分实际渲染视图的问题,所以请随意建议替代方案,但请不要费心建议我使用 Selenium、Watin 或其他 UI 来测试我的视图测试工具...我希望控件能够执行一些操作,例如操作和恢复某些测试的状态和数据信息,而基于 UI 的测试无法做到这一点。
这是我当前用来尝试渲染部分的代码:
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”且具有非空字符串值的项目。