I am writing code to test an C# MVC3 application. I can test the controllers but how do I test the code in the views? This includes javascript and razor styled code.
Are there any tools available which can mock out views or test views and javascript in C# in them?
Check out vantheshark's article, it describes how to mock the ASP.NET MVC View engine using NSubstitute.
The following is about testing the rendered output of the view. This textual output can for instance be loaded into a DOM for further analysis with XPath (using
XmlReader
for XHTML orHtmlAgilityPack
for SGML-style HTML). With some nice helper methods this allows easy check for checking specific parts of the view, such as testing//a[@href='#']
or anything else which you want to test. This helps making the unit tests more stable.One would expect that this is easy when using Razor instead of the "blown-up" WebForms engine, but it turned out to be quite the contrary, due to many inner workings of the Razor view engine and views using parts (
HtmlHelper
especially) of the HTTP request lifecycle. In fact, properly testing the generated output requires a lot of running code to get reliable and appropriate results, even more so if you use exotic stuff such as portable areas (from the MVCContrib project) and the like in the mix.The HTML helpers for actions and URLs require that the routing is properly initialized, the route dictionary is properly set up, the controller must also exist, and there are other "gotchas" related to loading data for the view, such as setting up the view data dictionary...
We ended up creating a
ViewRenderer
class which will actually instantiate an application host on the physical path of your web to be tested (can be statically cached, re-initialization for each single test is impractical due to the initialization lag):The
ApplicationHost
class in turn inherits fromMarshalByRefObject
since the host will be loaded in a separate application domain. The host performs all sorts of unholy initialization stuff in order to properly initialize theHttpApplication
(the code inglobal.asax.cs
which registers routes etc.) while disabling some aspects (such as authentication and authorization). Be warned, serious hacking ahead. Use at your own risk.The
ClearReadOnly
method uses reflection to make the in-memory web configuration mutable:The
ApplicationCatcher
is a "null"TextWriter
which stores the application instance. I couldn't find another way to initialize the application instance and get it. The core of it is pretty simple.This now enables us to render out almost any (Razor) view as if it were hosted in a real web server, creating almost a full HTTP lifecycle for rendering it:
Maybe this helps you to get to some results. In general many people say that the hassle of testing views is not worth the effort. I'll let you be the judge of that.