在单元测试期间渲染视图

我正在研究一个生成大型复杂报表的ASP.NET MVC 4 Web应用程序。 我想编写单元测试来渲染视图,以确保视图不会炸毁,具体取决于模型:

 [Test]
 public void ExampleTest(){                  
     var reportModel = new ReportModel();

     var reportHtml = RenderRazorView(
           @"....Report.MvcViewsReportIndex.cshtml", 
           reportModel);

     Assert.IsFalse(
         string.IsNullOrEmpty(reportHtml),
         "View Failed to Render!");          
 }

 public string RenderRazorView(string viewPath, object model){
    //WHAT GOES HERE?
 }

我已经在网络上看到了很多关于这方面的信息,但它要么反对测试,要么只能在Web请求的上下文中使用。

  • 争论 - 单元测试视图? - 这个结论应该在视图中没有逻辑,所以你应该只需要测试编译。 我认为在测试视图时有价值,以确保没有空引用异常,显示正确的部分等。
  • Web请求的上下文 - 将视图呈现为字符串 - 这是为了使视图在电子邮件中发送。 但是这种方法需要通过web请求(即有效的HttpContextBase )来调用。
  • 我一直在努力将视图渲染为一个字符串来处理Mocked HttpContextBase ,但是在使用Mocked ControllerContext时遇到了问题:

    你调用的对象是空的。 System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext,String [] locations,String [] areaLocations,System.Web.Mvc.ControllerContext.get_DisplayMode()在System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase上下文) String locationsPropertyName,String name,String controllerName,String cacheKeyPrefix,Boolean useCache,String []&SearchesLocations)

    这是我迄今为止的代码:

        public string RenderRazorView(string viewPath, object model)
        {
            var controller = GetMockedDummyController();
    
            //Exception here
            var viewResult = 
                ViewEngines.Engines.FindView(controller.ControllerContext, "Index", "");
    
            using (var sw = new StringWriter())
            {
                var viewContext =
                    new ViewContext(
                        controller.ControllerContext,
                        viewResult.View,
                        new ViewDataDictionary(model),
                        new TempDataDictionary(),
                        sw);
    
                viewResult.View.Render(viewContext, sw);
    
                return sw.ToString();
            }
        }
    

    我正在构建控制器:

        private Controller GetMockedDummyController()
        {
            var HttpContextBaseMock = new Mock<HttpContextBase>();
            var HttpRequestMock = new Mock<HttpRequestBase>();
            var HttpResponseMock = new Mock<HttpResponseBase>();
            HttpContextBaseMock.SetupGet(x => x.Request).Returns(HttpRequestMock.Object);
            HttpContextBaseMock.SetupGet(x => x.Response).Returns(HttpResponseMock.Object);
    
            var controller = new DummyController();
    
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Dummy");
    
            controller.ControllerContext = 
                new ControllerContext(
                    HttpContextBaseMock.Object,
                    routeData,
                    controller);
    
            controller.Url =
                new UrlHelper(
                    new RequestContext(
                        HttpContextBaseMock.Object,
                        routeData), 
                    new RouteCollection());
    
            return controller;
        }
    

    DummyController只是public class DummyController : Controller {}

    为View提供路径,我怎样才能从Test项目中将它渲染为HTML? 或者更具体地说,我怎样才能模拟出ControllerContext.DisplayMode


    假设你完全分离了关注点,是否有必要实例化控制器? 如果没有,那么也许你可以使用RazorEngine来测试你的视图。

    var contents = File.ReadAllText("pathToView"); 
    var result = Razor.Parse(contents,model);
    // assert here
    

    你将需要一个空的Controller来测试(例如TestController

    public class WebMvcHelpers
    {
        public static string GetViewPageHtml(object model, string viewName)
        {
            System.Web.Mvc.Controller controller = CreateController<TestController>();
    
            ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
    
            if (result.View == null)
                throw new Exception(string.Format("View Page {0} was not found", viewName));
    
            controller.ViewData.Model = model;
            StringBuilder sb = new StringBuilder();
            using (StringWriter sw = new StringWriter(sb))
            {
                using (System.Web.UI.HtmlTextWriter output = new System.Web.UI.HtmlTextWriter(sw))
                {
                    ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, controller.ViewData, controller.TempData, output);
                    result.View.Render(viewContext, output);
                }
            }
    
            return sb.ToString();
        }
    
        /// <summary>
        /// Creates an instance of an MVC controller from scratch 
        /// when no existing ControllerContext is present       
        /// </summary>
        /// <typeparam name="T">Type of the controller to create</typeparam>
        /// <returns></returns>
        public static T CreateController<T>(RouteData routeData = null)
                    where T : System.Web.Mvc.Controller, new()
        {
            T controller = new T();
    
            // Create an MVC Controller Context
            HttpContextBase wrapper = null;
            if (HttpContext.Current != null)
                wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
            //else
            //    wrapper = CreateHttpContextBase(writer);
    
    
            if (routeData == null)
                routeData = new RouteData();
    
            if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
                routeData.Values.Add("controller", controller.GetType().Name
                                                            .ToLower()
                                                            .Replace("controller", ""));
    
            controller.ControllerContext = new System.Web.Mvc.ControllerContext(wrapper, routeData, controller);
            return controller;
        }
    }
    
    public class TestController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
    
    链接地址: http://www.djcxy.com/p/83161.html

    上一篇: Render a View during a Unit Test

    下一篇: Nonblocking fifo