Unit testing Asp.Net MVC routes: which approach to choose? - asp.net-mvc

I'm new Asp.Net MVC and unit testing, so I apologize in advance if questions are somewhat stupid
When unit testing incoming routes, we must feed an URL into the routing system and verify that this URL is processed correctly.
1) But should the routes be tested separately ( thus a particular unit test would test no more than one route ) or should all routes be tested as a whole ( ie each unit test would test an instance returned by RouteCollection.GetRouteData(...); ) or both?
2) If the answer to 1) is that routes should be tested as a whole, then I have trouble understanding how many URLs would we need to pass into the routing system to be sure it works correctly:
a) as far as I can tell, wouldn't we need to pass at least as many as many URLs as there are registered routes, where each of these URLs should be processed by a different route ( this way all routes would get the chance to process one URL )?
b) Should all URLs be tested within a single unit test or should we have one unit test for each url? If the latter, then wouldn't the number of unit tests be the same as if each unit test would test no more than a single route?
c) Assuming we add a new route to the routing system, then we will most likely also need to modify existing unit tests in order for them to continue working properly, while if instead we were testing routes separately, then no modification of existing unit tests would be necessary?
thank you

You should be careful with these kinds of test as you could easily end up testing the Asp.Net MVC code, which is something that Microsoft presumably does. (For example: wouldn't these tests be testing the functionality of the GetRouteData method?)
Unless I'm misunderstanding you, it sounds like you just want to make sure you're configuring the route data correctly.
I would consider this type of configuration code to be simply part of creating your application's object graph, and not subject to unit testing. There are several reasons for this:
The configuration probably takes place in the composition root (e.g., within Application_Start in global.asax).
Any configuration initializes the system to a "technically correct" state. (Like if you replaced a production component with a test double. The system works; it just needs to be configured differently for production.)
It's very likely for these configurations to change in the future. For example, you mentioned that new routes could be added later. It's possible that existing routes may be changed, as well.
End-to-end/Smoke testing will make sure the application doesn't return a 404, which is usually what happens if the routing data is not configured properly.
After considering this, if you remain undeterred in testing the configuration then consider creating an abstraction that handles this configuration. That is, create a seam at the boundary where you are registering these routes.
This would allow you to mock out the calls to the Asp.Net MVC framework, and verify that you are sending it the expected configuration.

Related

UI Testing MVC with WatiN and injecting parameter to controller

First off, I may be barking up the wrong tree with this, so please correct me if I am wrong.
That said, I am trying to write sme UI unit tests that use WatIn. I am only working on a subset of the UI at present.
I have a controller called Product along with its associated views.
the Controller takes in a ProductRepository via the constructor.
What I would lie to do is to test that different product categories are rendered correctly, in different tests, so I need to pass in some kind of stubbed or mocked repository into my code.
My test is set up along the lines of;
using (var ie = new IE("http://localhost:2904/Product"))
{
...
}
So how do I pass in a repository to my controller that will provide the appropriate product? Once I have called the using statement, my system has launched the browser, so that is too late. But until the browser is launched, then the controller doesnt exist, so I can't inject in the appropriate repository.
Or have I fundamentally got this wrong, and I can only use WatiN against my database, and I need to program it to select a member of each type of product from the db, adn test that way?
I think, as you suggesting, you pick the wrong end of the problem. If I understand correctly, you don't need UI test and Watin but rather integration tests. I would suggest to create instance of controller, inject repositories as needed and mock other dependencies. Than you can switch repositories and so.
In UI tests you test your whole application from the top of UI down to database so it's hard to change behavior or mock some parts. Do you really need to test your functionality with UI? Wouldn't be better to test it only in controller or it's not option for your case?
Seems ok or I misunderstand you completely?

Virtual directory overriding MVC route

I have a web app, A, that has a virtual directory that is also an app, B. I've tried to create an MVC route in A such that the URL appears to be in the virtual directory but is still handled by A and not B. However, it seems to be being ignored. Is there a way of making the MVC route take priority over the virtual directory?
If you want App A to override App B, you're going to have to add some Url Rewriting configuration, not MVC routing logic, which, if you're using IIS7+ which, I believe, you should be set up in the web.config file for App A. IIS has to know which application to forward a request to; by the time MVC routing is invoked, the application has already been selected at that point (you cannot unselect B once the actual application is invoked * ). You also might be able to get away with setting up the url rewrite rules in App B to point to App A, but I'm not quite sure how that'd work.
Please note, what I'm saying about application invocation is very likely not strictly true. But to be honest, I don't know if I could give a completely accurate description of the lifecycle of a url rewritten request; I just hope I'm roughly approximating what happens in simplified terms. Just learn more about url rewriting in IIS and IIS7 request lifecycles visit the following links:
http://www.iis.net/learn/extensions/url-rewrite-module/using-the-url-rewrite-module
http://msdn.microsoft.com/en-us/library/bb470252(v=vs.100).aspx
So you got two apps A & B. You say you tried to create MVC route but in which app? If you can explain a bit more what you trying to achieve, it will be easier to answer.
ASP.net routes (also available in web forms) can take any form you want. The one thing you must keep in mind that the route maps are greedy. So if most generic route is found first it is not going to check anything below no matter what. So the order should be most specific and last one should be most general.
Check this post http://yogiorchard.azurewebsites.net/archiving-items-and-a-routing-lesson
Hope this helps

Unit testing an ASP.NET MVC 3 application

We have an ASP.NET WebForms application that we're going to convert to be ASP.NET MVC application - one of the reasons is so that we may take full advantage of Unit Testing and TDD.
Our current WebForms application makes heavy use of HttpModules. We're currently debating whether we should stick with HttpModules or use Global Filters (any advice here would be great).
However, with my few "hello world" test MVC applications, I've not worked out how to get the HttpModule (or indeed the Global Filter) code to fire when Unit testing.
Maybe I'm wrong, but it seems to me that I need this to be part of my unit-testing (integration testing) otherwise it can't be a true representation of what's going on in my Production code.
Any guidance would be most welcome.
Thanks
Griff
PS - I added the following after the initial responses to my question.
Simple made-up Use Case
In Production
Browser makes a Request for a Controller Method
HttpModule fires (or Global Filter) - this sets a static Guid property to have a value.
The controller method takes this Guid value and uses it in its subsequent logic
Correct result is then returned to the browser
In Unit Testing
Unit test calls the same Controller Method
The HttpModule (or Global Filter) does not fire - the static Guid property has a value of Guid.Empty
The controller method takes this Guid value, but throws an error because it was an Empty Guid
Unit test fails
My thoughts are:
if a Controller relies upon an HttpModule (or Global Filter) to run first, then the HttpModule is a dependency and therefore the results of it's action must be Stubbed for the test to be a true Unit Test.
If the test is to include the effect of the HttpModule (or Global Filter) to run, then this would be an Integration test (though it's still not clear yet how to get the HttpModule or Global Filter to run as part of the Integration test)
The HttpModule (or Global Filter) should have their own set of Unit Tests
I think this is the approach I'll take, but if anyone could suggest how I get my Integration test (as described above) to work then I'd be most grateful.
The problem as I see it is that my TEST project becomes the "start up" project when running my tests, so the HttpModules (defined in the ASP.NET MVC's web.config file) and the Global Filters (defined in the ASP.NET MVC's global.asax file) will not run because the web.config and global.asax files are not executed. So the question remains: how do I get these to run in my Integration test?
Thanks everyone
Griff
You shouldn't be testing to check if the global filter fires or not. The mechanism that fires the code isn't your code, it's part of the framework so the framework team is supposed to test that.
Instead you should simply be testing to make sure that the global filter has been applied.
Whether or not to call a HttpModule or Global Filter is handled by the Framework. You shouldn't be worried about Unit Testing things that are handled by the Framework. Your Unit Tests should only test that your HttpModule or Global Filter behave properly when called.
I would mock the http modules and repositories to unit test the controllers and services, in my view that's how you unit test. the global filters and httpmodules you can test it with end to end tests. Hope it helps.

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).
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.
mspec mvc extensions

What are the most important things to test in an ASP.NET MVC application?

Most of the stackoverflow posts about ASP.NET MVC unit testing talk about a specific issue or specific thing to test such as testing HtmlHelpers. Others on the subject of best practices have surprisingly few answers. Available videos I have watched are completely useless in my opinion - and mind blowingly long (by the time you've watched 1.5 hours and not learned anything).
What I want to know from people who've actually been doing this is :
What are the most important things to test first
What doesn't need testing (shock horror for me saying that but I'm not after 100%)
What is hard to test and how have you overcome difficult thins to test.
What things can break in refactoring that a test won't catch.
I'm not new to how to unit test - but I'm very new to actually doing it consistently. I'd really appreciate lessons learned from those who are experts in unit testing ASP.NET MVC.
I'm really looking for specific things you might only find out after having tried it - not jsut general advice like 'use interfaces' - although of course any suggestions are welcome.
Oh and lets say I've decided to use Microsoft's unit testing - just becasue its already there. I think all answers would apply to all testing frameworks though.
Test your routing. You should use RouteLink to remove ambiguity when you generate a URL in your View, but when you submit a URL, you are dependent upon the routing system to select the correct route. So test that the URL patterns you support do in fact return the correct route.
Test your controller actions. Use a mock repository, and test that manually invoking each action has the results you expect.
Test all business logic in your model. This is obvious, and little different from non-MVC applications.
Test any custom view helpers you write. Although I don't generally unit test views, view helpers are different.
Test your JavaScript. There are unit testing frameworks for this, that testing JavaScript is so easy that such frameworks are hardly necessary. But testing JavaScript is incredibly important, due to the tendency of the language to hide errors from you.
If you have written any custom model binders, they need special attention. For one thing, it is a lot easier to debug a model binder via a unit test than when it is "live" in the application.
I'd like to elaborate on testing controller actions:
Verify you get the proper ActionResult. A redirect is different from a view.
Also verify the expected view name. If you rely on the default view, it should be empty.
Verify you get the proper view model.
Verify all branches in your action. Keep them to a minimum and move them to a helper / service when they grow too many.
In short, verify anything from the ActionResult that you will use.
I dont think the answer has to be specific to ASP.NET MVC.
Like any other application, the most important thing you have to test is your core logic.
That is, your model code and your controller actions.

Resources