views:

153

answers:

2

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));

    }
A: 

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.

Aaronaught
thanks i'll try that out
fregas
A: 

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);

    // Make the UrlHelper with empty route data
    var requestContext = new RequestContext(httpContextBase, new RouteData());
    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.

Parched Squid