C# 在单元测试期间呈现视图-ControllerContext.DisplayMode
我正在开发一个ASP.NET MVC 4 web应用程序,它可以生成大型复杂的报告。我想编写渲染视图的单元测试,以确保视图不会因模型而异:C# 在单元测试期间呈现视图-ControllerContext.DisplayMode,c#,asp.net-mvc,asp.net-mvc-4,unit-testing,rhino-mocks,C#,Asp.net Mvc,Asp.net Mvc 4,Unit Testing,Rhino Mocks,我正在开发一个ASP.NET MVC 4 web应用程序,它可以生成大型复杂的报告。我想编写渲染视图的单元测试,以确保视图不会因模型而异: [Test] public void ExampleTest(){ var reportModel = new ReportModel(); var reportHtml = RenderRazorView( @"..\..\Report.Mvc\Views\Report\I
[Test]
public void ExampleTest(){
var reportModel = new ReportModel();
var reportHtml = RenderRazorView(
@"..\..\Report.Mvc\Views\Report\Index.cshtml",
reportModel);
Assert.IsFalse(
string.IsNullOrEmpty(reportHtml),
"View Failed to Render!");
}
public string RenderRazorView(string viewPath, object model){
//WHAT GOES HERE?
}
我在web上看到了很多关于这方面的信息,但它要么反对测试VIE,要么只能在web请求的上下文中使用
- 反对——这得出结论,视图中不应该有逻辑,所以您只需要测试编译。我认为测试视图是有价值的,以确保没有空引用异常,显示了正确的部分,等等
- Web请求的上下文--这是呈现要在电子邮件中发送的视图。但这种方法需要通过web请求(即有效的
)调用HttpContextBase
HttpContextBase
,但在使用模拟的ControllerContext
时遇到了问题:
对象引用未设置为对象的实例。
位于System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase上下文)
在System.Web.Mvc.ControllerContext.get_DisplayMode()中
位于System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext ControllerContext,String[]位置,String[]区域位置,String locationsPropertyName,String name,String controllerName,String cacheKeyPrefix,Boolean useCache,String[]和searchedLocations)
这是我目前掌握的代码:
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;
}
专用控制器GetMockedDummyController()
{
var HttpContextBaseMock=new Mock();
var HttpRequestMock=new Mock();
var HttpResponseMock=new Mock();
SetupGet(x=>x.Request).Returns(HttpRequestMock.Object);
HttpContextBaseMock.SetupGet(x=>x.Response).Returns(HttpResponseMock.Object);
var controller=new DummyController();
var routeData=新routeData();
添加(“控制器”、“虚拟”);
controller.ControllerContext=
新控制器上下文(
HttpContextBaseMock.Object,
罗特达塔,
控制器);
controller.Url=
新UrlHelper(
新请求上下文(
HttpContextBaseMock.Object,
路特达),
新路线收集());
返回控制器;
}
DummyController
只是公共类DummyController:Controller{}
问题
给出视图的路径,如何从测试项目将其呈现为HTML?或者更具体地说,我如何模拟
ControllerContext.DisplayMode
?假设您完全分离了关注点,是否需要实例化控制器?如果没有,那么也许您可以使用来测试您的视图
var contents = File.ReadAllText("pathToView");
var result = Razor.Parse(contents,model);
// assert here
您需要一个空的
控制器
用于测试(例如TestController
)
公共类WebMvcHelpers
{
公共静态字符串GetViewPageHtml(对象模型,字符串viewName)
{
System.Web.Mvc.Controller=CreateController();
ViewEngineResult结果=ViewEngines.Engines.FindPartialView(controller.ControllerContext,viewName);
如果(result.View==null)
抛出新异常(string.Format(“未找到视图页{0}”,viewName));
controller.ViewData.Model=模型;
StringBuilder sb=新的StringBuilder();
使用(StringWriter sw=新StringWriter(sb))
{
使用(System.Web.UI.HtmlTextWriter输出=新的System.Web.UI.HtmlTextWriter(sw))
{
ViewContext ViewContext=新的ViewContext(controller.ControllerContext、result.View、controller.ViewData、controller.TempData、output);
result.View.Render(viewContext,输出);
}
}
使某人返回字符串();
}
///
///从头创建MVC控制器的实例
///当不存在现有ControllerContext时
///
///要创建的控制器的类型
///
公共静态T CreateController(RouteData RouteData=null)
其中T:System.Web.Mvc.Controller,new()
{
T控制器=新的T();
//创建MVC控制器上下文
HttpContextBase包装器=null;
if(HttpContext.Current!=null)
包装器=新的HttpContextWrapper(System.Web.HttpContext.Current);
//否则
//包装器=CreateHttpContextBase(编写器);
if(routeData==null)
RoutedData=新RoutedData();
如果(!routeData.Values.ContainsKey(“控制器”)和&!routeData.Values.ContainsKey(“控制器”))
routeData.Values.Add(“controller”,controller.GetType().Name
.ToLower()
.更换(“控制器”);
controller.ControllerContext=new System.Web.Mvc.ControllerContext(包装器、路由数据、控制器);
返回控制器;
}
}
公共类TestController:控制器
{
公共行动结果索引()
{
返回视图();
}
}
no,我不需要调用控制器或其方法。我已经有了一个模型,想用它来渲染一个视图,所以我要试试这个!您是否使用此选项渲染“MVC”视图。我无法让它编译像@Styles.Render()
这样的语句。引擎抱怨它缺少程序集,即使我已经添加了它们。查看编译后的输出后,看起来正在基于web.configsystem.web\pages\namespace
添加using语句。有没有办法添加这些内容?RazorEngine链接中有文档讨论了如何使用ha
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();
}
}