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.
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
?
The purpose of a unit test in software engineering is to verify the behavior of a relatively small piece of software, independently from other parts. Unit tests are narrow in scope, and allow us to cover all cases, ensuring that every single part works correctly.
Assuming you have complete separation of concerns, is it necessary to instantiate the controller at all? If not, then perhaps you can use RazorEngine to test your views.
var contents = File.ReadAllText("pathToView");
var result = Razor.Parse(contents,model);
// assert here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With