Unit testing MVC3 Razor helpers/views without strings
Asked Answered
G

4

9

I am trying out the MVC3 Razor view engine, and one the features that I am exploring is the ability to unit test views.

I have seen a number of examples where Razor views can be compiled into an assembly and rendered into a string. The problem is that it renders as a string, so I am left with doing string searches!

Here is what I am trying to do.

  1. Create a Razor helper
  2. Compile helper
  3. Run compiled helper, passing in a ViewModel
  4. Get the output of the helper as some sort of HTML/XML/tree structure

The reason that I want to do this is so that I can test for specific parts of the output. The helper will likely spit out HTML that includes various output gunk. What I want to do is to see if there is a Checkbox with a particular value (for example). If you have seen Selenium tests, it is similar to what I would like to do, except not as server driven tests.

Is there some way to get compiled Razor (or other view engine) views to emit something other than strings?

Geralyngeraniaceous answered 29/1, 2011 at 2:40 Comment(0)
G
4

The short answer is no, because view engines' purpose in life is to spit out strings. Parsing those strings into an XML document is a way to give them a little structure, like @Craig-M suggested. But what you have to ask yourself is what you're really testing. If your view compiles and generates some kind of HTML, there can be three problems with what it generated:

  • the data it displays is not correct. You would test for this at the controller level, so you can ignore it during view testing.
  • the MVC framework had an error and it generated the wrong HTML string. You don't worry about this, because MVC has its own test suite and thanks to separation of concerns, it's not your problem.
  • the HTML has broken the user interface.

That last one would be very nice to test for, but why not test for it in javascript unit tests? Check out popular javascript unit test suites like JsUnit, FireUnit, QUnit, etc. They would all do a much better job than you could do of parsing out Razor output.

I think the value assigned to a checkbox would probably be tested for in Controller testing. But to use your example, testing your checkbox's value could be $('#theCheck').val() == 'the value'. And you can run these against a website running with dependency injected repositories or services to control things like 'the value'.

Just a thought.

Grave answered 17/2, 2011 at 22:32 Comment(2)
Thanks for the excellent answer. The reason for testing at the HTML level is to test logic in the view. For example, if I pass in a ViewModel that contains Products, and has a property of in stock. If a product has stock == 0, don't show a purchase link. Later, I add logic in the ViewModel to ensure that products never have stock == 0, but instead use IsInStock? property. I want a test that will fail due to it not producing the right HTML. One way to write this test is to construct a legit ViewModel, pass it to the view, and check that the link is/is not generated. Make sense? Thanks,Geralyngeraniaceous
Yeah, I follow. Checking that the link exists in QUnit would be something simple like: test("testing for link", function() { ok( $('#myLink').length == 1, "link present" ); });Grave
P
1

One way you could go about this is to parse the html string into an XDocument and have your assembly return it. Then you can query against it with LINQ in your tests.

Edit: I'm trying to figure out a Razor test strategy too. I'd be interested to know how you get the helper to work. So far, I'm drawing a blank in getting them rendered to strings outside of the MVC framework.

Poulson answered 16/2, 2011 at 16:49 Comment(3)
That is the direction I am going right now. Even with Razor, it is kind of a hassle to spin up get all the dependencies working right (e.g., TempData) for testing a view. I might look into other View Engines, but I think that it be ASP.NET MVC that is the problem. Let me know if you make any progress! ThanksGeralyngeraniaceous
I spent two days trying various different methods to get the views rendered to a string. No luck so far. Every path came up against some sort of resistance such as was needing to instantiate an internal class or not being able to use the MVC helpers. Since we're already doing WebAii testing on this project, I ran out of time to make it work and had to abandon my effort. I'm very interested in doing this on my own projects though and will definitely post back here if/when I come up with a solution.Poulson
A tad late, but I posted parts to get a working unit test harness for Razor views in the following question: #8720722Bohemianism
H
1

How about rendering your views to html and then sending that html to HtmlAgility library? That way you can easily traverse/navigate your html. I don't think there is any way to do that with MVC itself.

Hage answered 8/3, 2011 at 22:21 Comment(1)
This is the direction that I ended up going. With the rise of HTML5, it looks like expecting real XML is going to a problem later.Geralyngeraniaceous
U
0

It looks like Microsoft has its own answer of how to produce HTML from views, for the purpose of unit testing.

Undis answered 1/5, 2012 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.