random .NET and web development musings

In order to use the UrlHelper class in your tests, you need to construct it with a ControllerContext, which consists of an HttpRequest and an HttpResponse. Unfortunately these are quite difficult to construct, as you’ll know if you’ve ever tried. Luckily, the UrlHelper doesn’t use much of these two classes, only a few properties, making them fairly easy to mock.

The first thing you need to do is get your routes, usually declared in your Global.asax MvcApplication

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

Then you need to mock an HttpRequest

var request = MockRepository.GenerateStub<HttpRequestBase>();
request.Stub(x => x.ApplicationPath).Return("/");
request.Stub(x => x.Url).Return(new Uri("http://localhost/a", UriKind.Absolute));
request.Stub(x => x.ServerVariables).Return(new System.Collections.Specialized.NameValueCollection());

Then you need to mock the HttpResponse

var response = MockRepository.GenerateStub<HttpResponseBase>();
response.Stub(x => x.ApplyAppPathModifier(Arg<string>.Is.Anything))
    .Return(null)
    .WhenCalled(x => x.ReturnValue = x.Arguments[0]);

Then you can simply stick these two mocks onto a mock context, and use that to create your UrlHelper instance and set them on the controller you are testing:

var context = MockRepository.GenerateStub<HttpContextBase>();
context.Stub(x => x.Request).Return(request);
context.Stub(x => x.Response).Return(response);

var subjectUnderTest = new MyController(); // this is the controller you are testing

subjectUnderTest.ControllerContext = new ControllerContext(context, new RouteData(), subjectUnderTest);
subjectUnderTest.Url = new UrlHelper(new RequestContext(context, new RouteData()), routes);

Job done.

Now go and use OpenRasta and not have any of these problems.