jeudi 22 janvier 2015

Render a View during a Unit Test - ControllerContext.DisplayMode

I am working on an ASP.NET MVC 4 web application that generates large and complicated reports. I want to write Unit Tests that render a View in order to make sure the View doesn't blow up depending on the Model:



[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?
}


I have seen a lot of information about this around the web, but it's either arguing against testing vies, or can only be used in the context of a web request.



  • Arguing Against - Unit Testing the Views? - This concludes there should be no logic in the View so you should only need to test compilation. I think there is value in testing the View to make sure there aren't Null Reference Exceptions, the correct sections are shown, etc.

  • Context of a Web Request - Render a view as a string - This is to render a View to be sent in an email. But this approach requires being called via a web request (ie a valid HttpContextBase).


I have been working to adapt Render a view as a string to work with a Mocked HttpContextBase, but have been running into problems when using a Mocked ControllerContext:



Object reference not set to an instance of an object. at System.Web.WebPages.DisplayModeProvider.GetDisplayMode(HttpContextBase context) at System.Web.Mvc.ControllerContext.get_DisplayMode() at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations)



This is the code I have so far:



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();
}
}


I'm building the Controller:



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;
}


The DummyController is just public class DummyController : Controller {}


Question


Give the path to a View, how can I render it to HTML from a Test project? Or more specifically, how can I mock out the ControllerContext.DisplayMode?


Aucun commentaire:

Enregistrer un commentaire