Asp.net-mvc – ASP.NET MVC: Unit testing controllers that use UrlHelper

asp.net-mvcunit testingurlhelper

One of my controllers actions, one that is being called in an Ajax request, is returning an URL to the client side so it can do a redirection. I'm using Url.RouteUrl(..) and during my unit tests this fails since the Controller.Url parameter is not pre-filled.

I tried a lot of things, among others attempting to stub UrlHelper (which failed), manually creating a UrlHelper with a RequestContext that has a stubbed HttpContextBase (which failed on a RouteCollection.GetUrlWithApplicationPath call).

I have searched Google but found virtually nothing on the subject. Am I doing something incredibly stupid using Url.RouteUrl in my Controller action? Is there an easier way?

To make it even worse, I'd like to be able to test the returned URL in my unit test – in fact I'm only interested in knowing it's redirecting to the right route, but since I'm returning an URL instead of a route, I would like to control the URL that is resolved (eg. by using a stubbed RouteCollection) – but I'll be happy to get my test passing to begin with.

Best Answer

Here is one of my tests (xUnit + Moq) just for similar case (using Url.RouteUrl in controller)

Hope this helps:

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);

var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");

var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var controller = new LinkbackController(dbF.Object);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);