0

Has anyone mocked FriendlyUrls for unit testing?

I am writing a test that needs to mock asp.net FriendlyUrls. The call I need to mock specifically is Request.GetFriendlyUrlSegments(). I am using MS Fakes.

Here is my test so far:

// Arrange
            var httpContext = TestHelper.StubHtppContext("", "http://localhost/content.aspx/area/controller/action/OtherRouteValue", "");
            var httpContextBase = new HttpContextWrapper(httpContext);

            RouteTable.Routes.MapRoute(
                "RouteName",
                "Area/{controller}/{action}/{id}/{OtherRoute}",
                new {action = "Index", id = UrlParameter.Optional, OtherRoute = UrlParameter.Optional});

            RouteTable.Routes.EnableFriendlyUrls();

            var segments = new List<String> {"Controller", "Action", "Id", "OtherRoute"};


            using (ShimsContext.Create())
            {
                ShimHttpContext.CurrentGet = () => httpContext;

                ShimFriendlyUrl.SegmentsGet = () => segments;

                // Act 
                RouteData result = MvcUtility.GetRouteValuesFromUrl();

                // Assert
                Assert.IsNotNull(result, "Expected RouteData to be created.");
            }

        }

The relevant Part of the system under test:

 public static RouteData GetRouteValuesFromUrl()
 {
    var request = System.Web.HttpContext.Current.Request;
    var segments = request.GetFriendlyUrlSegments();
    //Other code
 }

I would expect for segments to use my shim get and return my list of segments.

My code works when I run it in the web context, I just need to find a way to unit test it and the first step is mocking shim/stub this request.GetFriendlyUrlSegments() call.

twifosp
  • 277
  • 2
  • 7
  • 16
  • 2
    To make your code testable, you should use an injected `HttpContextBase` instead of `HttpContext.Current`. – SLaks Jan 29 '14 at 17:19
  • @Slaks, That's a good point, however I'm not clear on how that would help me shim the method call of Request.GetFriendlyUrlSegments(). Can you elaborate? – twifosp Jan 29 '14 at 17:36
  • 1
    Hmm; looking further, it won't help here, unless the implementation of the `GetFriendlyUrlSegments` extension method uses data you can fake. (try a decompiler?) – SLaks Jan 29 '14 at 17:42
  • Good suggestion. Inspecting the dll shows that the method makes a (string)httpRequest.GetRouteData().DataTokens["FriendlyUrlFileExtension"] ?? string.Empty; – twifosp Jan 29 '14 at 18:46

1 Answers1

0

Based on slaks suggestion, the right data to fake here is the Request.RequestContext.RouteData. It needs a DataToken with a "FriendlyUrlSegments" key.

The corrected and working test:

var httpContext = TestHelper.StubHtppContext("", "http://localhost/content.aspx/area/controller/action/OtherRouteValue", "");
        var httpContextBase = new HttpContextWrapper(httpContext);

        RouteTable.Routes.MapRoute(
            "RouteName",
            "Area/{controller}/{action}/{id}/{OtherRoute}",
            new {action = "Index", id = UrlParameter.Optional, OtherRoute = UrlParameter.Optional});

        RouteTable.Routes.EnableFriendlyUrls();

        var segments = new List<String> {"Controller", "Action", "Id", "OtherRoute"};

        var requestContext = new StubRequestContext(httpContextBase, new RouteData());

        var mockedRouteData = new RouteData();
        mockedRouteData.DataTokens.Add("FriendlyUrlSegments", segments);

        requestContext.RouteDataGet = () => mockedRouteData;

        using (ShimsContext.Create())
        {
            ShimHttpContext.CurrentGet = () => httpContext;
            ShimHttpRequest.AllInstances.RequestContextGet = request => requestContext;

            // Act 
            RouteData result = MvcUtility.GetRouteValuesFromUrl();

            // Assert
            Assert.IsNotNull(result, "Expected RouteData to be created.");
twifosp
  • 277
  • 2
  • 7
  • 16