Introduction
Unit Testing razor views of an ASP.NET MVC is extremely difficult, maybe you tried Selenium in combination with a hosted environment in IIS (or IIS Express), but with such a setup, you are basically performing integration testing.
To be able to perform true unit testing, we need to isolate MVC features from rendering the view, which means no authorization, no model binding, no request validation, no filter actions, no method selectors, and no action invocation.
You should only need to specify the view content, the view model, view data, temp data, bundles, etc. and a controller context because razor happens to need one to expose UrlHelper
and HtmlHelper
.
So why not use Razor Engine or similar? Simply because Razor Engine has a distinct application where MVC features are not needed, i.e., Razor Engine does not support the view '~/Views/Home/Index.cshtml' from the default ASP.NET MVC project template, but if you need full support of Razor features, then we need something else, that is where Xania.AspNet.Simulator
comes into play.
About the Code
The sample code is based on ASP.NET MVC 4 because Xania.AspNet.Simulator
(Xim) does not support other versions yet. The web application is created from Internet Application project template that consists of rich Razor features to demonstrate the power of Xim. To install Xim in your own project, run the following in a Package Manager Console
PM > Install-package Xania.AspNet.Simulator
The main part of the demo code is the method IndexContent
in HomeController
. First, we instantiate content providers to help us find the views of the project.
var appContent = new DirectoryContentProvider(projectDir);
Next, we create an MVC application which represents hosting environments with Routes, Bundles, ViewEngines, Model binder, etc. This hosting environment construct is intended as a flexible and lightweight replacement of System.Web.Hosting.HostingEnvironment
and especially to prevent the use of System.Web.BuildManager
.
var mvc = new Xania.AspNet.Simulator.MvcApplication(appContent)
.WithBundles(BundleConfig.RegisterBundles);
The last step of the setup code is to create a ControllerAction
to represent the Index
action method of HomeController
. The method Index
itself will not be executed but instead the runtime context is derived form it to serve the rendering of the Razor view:
var action = mvc.Action(new HomeController(), "index");
Finally, we can render the view Views\Home\Index.cshtml to an in memory StringWriter
.
using (var contentStream = appContent.Open(@"Views\Home\Index.cshtml")
{
var writer = new StringWriter();
action.RenderView(contentStream, writer);
return writer.ToString();
}
Points of Interest
Xania.AspNet.Simulator
has many more features to support true unit testing of different parts of an MVC application. Check out the following articles as well: