Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test that Asp.Net MVC Views are rendered without exceptions?

I have come up with a small issue in my application.

I changed the namespace of my main application to be from MyApp.Models to MyApp.ViewModels so that the namespaces were less confusing overall (since that namespace only has view models and no business models). I changed all the references I could find, including in my views, and I re-ran all my unit tests and went through the application, and all seemed fine.

A few days later I got a report that the registration page had an error when it was brought up. After looking it turns out I forgot to fix the namespace on the registration page, and thus it was failing to compile the view.

This worries me. The whole point of unit testing, and one of the biggest lures of Asp.Net MVC, is to be able to have confidence in your application by having everything tested individually automatically so that you know immediately when your modification breaks parts of the system. Views right now seem like a major hole in this.

To be clear, I am aware you are able to turn on pre-compiling a views. However, I do not like this option as it's not a good idea to have this on all the time (as it makes compiling a new build very, very slow), and having a separate configuration scheme for this means it's up to the user to remember to attempt to compile with that configuration scheme to check for view compile errors.

This also completely bypasses checking for runtime errors that may occur. For example, lets say you change the viewmodel that a strongly-typed view is expecting. You would then update the unit test to make sure that the Controller.Action() is returning a view result with the correct view model type, but that does nothing to make sure that the actual view was updated correctly for the new view, and yet this scenario will cause a run-time exception. This is an easy scenario to occur, especially since if the differences in the two view models are only seen in partials used within the view.

Other examples of code that can cause runtime exceptions in views are incorrect loops (possibly caused by changes in a view model), code that checks a user's role (so buttons are only shown for users with credentials), incorrect casts (e.g. for converting a collection into a select list), incorrect code to sort a collection (how a collection is sorted in the display can construed as a view concern, not a controller or view model concern), if strings used for locations of files don't work correctly (T4MVC doesn't integrate well with some things, such as Telerik's script registration system) etc...

The way I see it, there are many things that can cause an exception to occur in the process of rendering a view, and I can't seem to find any way to create unit or integration tests to determine when these occur. I would feel more comfortable if I did not have to check every page to make sure I missed a compile time or runtime error for something that a standard unit test should be able to catch.

What options do I have to do this?

I would prefer to stay away from WaTiN and other GUI testing tools, as for this I am not interested in the actual display of the page, I only want to know if the view renders or if an exception occurs and do not need the overhead of Watin running an IE instance for each test (I also think this will cause issues if I go with continuous integration at a later point).

like image 945
KallDrexx Avatar asked May 16 '11 19:05

KallDrexx


1 Answers

If you don't want to use WaTIN and IE, how about firing up your web site in IIS Express, and then using HttpWebRequest over each of your Views' urls to check the result is 200 OK. This is a complete integration test.

Otherwise, you have to get the ViewResult from your controller, and call the ExecuteResult method passing in a ControllerContext containing a stubbed HttpContextBase. This gives more of a true unit test, and would be faster, but you've got a lot of mocking and stubbing to do before it will work.

like image 148
Tim Rogers Avatar answered Sep 28 '22 16:09

Tim Rogers