Ama*_*iel 13 c# asp.net-mvc razor asp.net-mvc-3
好的,所以我使用MVCContrib TestHelper对我的控制器进行单元测试,效果很好.
和很多人一样,通过单元测试我真的是指这里的集成测试,我想至少确保我的视图在没有错误的情况下呈现给定模型提供...否则我会错过一大堆与模型基本相关的错误虽然我正在测试控制器(如果模型属性为null,则视图不呈现).
无论如何,我开始试图弄清楚如何做到这一点(也就是谷歌搜索如何做到这一点).似乎最简单的方法是构造一个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'的项目,其中包含非空字符串值.
ste*_*e_c 30
您可能已经解决了这个问题,但我遇到了类似的问题并解决了设置RouteData的问题,方法是重置控制器上的ControllerContext,如下所示:
RouteData routeData = new RouteData();
routeData.Values.Add("someRouteDataProperty", "someValue");
ControllerContext controllerContext = new ControllerContext { RouteData = routeData };
controller.ControllerContext = controllerContext;
然后在控制器中RouteData.Values.ContainsKey("someRouteDataProperty")按照您在测试中设置的方式工作.
这是有效的,因为有一个ControllerContext的无参数构造函数,故意在那里允许模拟等.
| 归档时间: | 
 | 
| 查看次数: | 20791 次 | 
| 最近记录: |