How can I test route/action resolution of URL with query string?
Asked Answered
C

1

6

I'm trying to use code such as the following in my unit tests,

/* Test setup code */
_routes = RouteTable.Routes;
MvcApplication.RegisterRoutes(_routes); //set up the routes as they would be in actual application
/* test code */
Expression<Func<SearchController, ActionResult>> actionFunc;
actionFunc = action => action.Results("x", 3, null);
RouteTestingExtensions.Route(
   "~/Search/Results?searchText=x"
).ShouldMapTo<SearchController>(actionFunc);

The problem is, this is failing with "Expected Results by was Results?searchText=x"

Does anyone have a solution which would allow me to test that a URL (with query string) resolves to the correct controller, action and arguments?

FYI, I don't have an explicit route setup in Global.asax.cs, as the default route works for the actual app - it just doesn't work in this test.

Caducous answered 25/5, 2010 at 17:4 Comment(2)
Any suggestions as to other testHelpers that make route testing as easy as this one?Caducous
Maybe these articles by Phil Haack will help: 1. https://haacked.com/archive/2007/12/17/testing-routes-in-asp.net-mvc.aspx 2. https://haacked.com/archive/2008/03/13/url-routing-debugger.aspxPinery
C
10

IMHO it makes sense to unit test only custom routes. Testing that query string parameters will be translated to controller action arguments is unnecessary and doesn't really bring any value to your application. This work is done by the default model binder and is extensively unit tested by Microsoft (I hope).

This being said MVCContrib.TestHelper allows you to elegantly test custom routes. Suppose for example that you have implemented paging in your application and defined a custom route to have pretty urls for SEO:

routes.MapRoute(
    "Custom",
    "foo/{startPage}/{endPage}",
    new 
    { 
        controller = "Search", 
        action = "Results", 
    }
);

and here's the associated controller:

public class SearchController : Controller
{
    public ActionResult Results(int startPage, int endPage)
    {
        return View();
    }
}

This route could be tested like this:

"~/foo/10/20".ShouldMapTo<SearchController>(c => c.Results(10, 20));

This will effectively test that the default controller is Search, the default action is Results and that both startPage and endPage parameters will be initialized to their respective values from the route.

Cosmetician answered 29/9, 2010 at 21:38 Comment(2)
This would work & is what I was doing, but the problem is that I wanted to test a URL with a query string (i.e. "/Controller/Action?Query"), and the TestHelper doesn't handle query strings. I could've changed the search to use path rather than query, but that would have involved client side JS to build a URL for the request - in this case I wanted no JS, just a simple form submission GET. You may be right however, that it just isn't worth testing. The project I was working on when I asked it was my first foray into MVC, and I'm still not sure to what extent the "magic" parts should be tested.Caducous
What if my custom route only works with a query string? (Besides my route, my controller's action signature has an id parameter which is passed by the query string - now how can I unit test that custom route?)Kaon

© 2022 - 2024 — McMap. All rights reserved.