Unit Testing UrlHelper Extension Methods

2.2k views Asked by At

I'm trying to create unit tests to make sure my extension methods for UrlHelper work? Does anyone know how to do this? I'm using MVC 1.0 and MvcContrib. I can test the routes but can't test code like this:

    public static string MoreFloorplans(this UrlHelper urlHelper, long productID, int pageIndex)
    {
     return urlHelper.Action<CatalogController>(x => x.GetRelatedProducts(productID, pageIndex));

    }
2

There are 2 answers

0
Aaronaught On

In order to create a UrlHelper, you need a RequestContext. In order to create a functioning RequestContext, you need an HttpContextBase and a RouteData. The second, RouteData, should be straightforward to construct. The HttpContextBase, you have to mock.

For that, I'd suggest you look at Scott H's MvcMockHelpers. Parts of that are a little old, but I think it's good enough for this particular test - all you really need is the FakeHttpContext method and its dependencies. If you go pick up that library, your code would look something like:

[TestMethod]
public void Can_write_more_floorplans()
{
    const long productID = 12345;
    const int pageIndex = 10;

    var httpContext = FakeHttpContext();  // From the MvcMockHelpers
    var routeData = new RouteData();
    var requestContext = new RequestContext(httpContext, routeData);
    var urlHelper = new UrlHelper(requestContext);
    string floorplans = MoreFloorplans(urlHelper, productID, pageIndex);
    Assert.AreEqual(some_string, floorplans);
}

I know you say you're trying to use the MvcContrib TestHelper project, but as far as I know, that library is all about testing controllers. I'm not sure if it's really granular enough to test a lower-level component. You don't really need all the stuff in there anyway; all you need is a RequestContext.

0
Craig Celeste On

I followed the instructions from Aaronaught and Scott H but it took some goofing around. I ended up with something like this.

public UrlHelper GetUrlHelper(
        string fileName = "/",
        string url="http://localhost", 
        string queryString="")
{
    // Use routes from actual app
    var routeCollection = new RouteCollection();
    MvcApplication.RegisterRoutes(routeCollection);

    //Make a request context
    var request = new HttpRequest(fileName, url, queryString);
    var response = new HttpResponse(new StringWriter());
    var httpContext = new HttpContext(request, response);
    var httpContextBase = new HttpContextWrapper(httpContext);
    var requestContext = new RequestContext(httpContextBase, new RouteData());

    // Make the UrlHelper with empty route data
    return new UrlHelper(requestContext, routeCollection);
}

public void MoreFloorplans_ReturnsExpectedUrl()
{
    var urlHelper = GetUrlHelper();
    var actualResult = urlHelper.MoreFloorPlans(1,2);
    Assert.AreEqual("/MoreFloorPlans/1/2", actualResult);
}

Note that you should be testing your extension method, not UrlHelper itself, so setting up the RouteData in the RequestContext is probably out of scope.