In my previous post I explain how to create advance routing system.but testing is one of thing that need in each and every step of application life cycle.so my this post show you how to test a routes easily using unit testing.
In web application all things begin with HttpContext.as Unit test is not a web application it does not use HttpContext but for testing route routes system need a URL and it ask for HttpContext.Request.AppRelativeCurrentExecutionFilePath.for that we have to create mock for HttpRequest,HttpResponse and we overrides a request for this property in HttpContextBase with mock of HttpRequestBase and HttpResponseBase. we use Moq tool for create mock of this classes.
Private Function CreateHttpContext(Optional targerUrl As String = Nothing, Optional HttpMethod As String = "GET") As HttpContextBase 'create mock request Dim mockRequest As New Mock(Of HttpRequestBase) mockRequest.Setup(Function(r) r.AppRelativeCurrentExecutionFilePath).Returns(targerUrl) mockRequest.Setup(Function(r) r.HttpMethod).Returns(HttpMethod) 'create mock response Dim mockResponse As New Mock(Of HttpResponseBase) mockResponse.Setup(Function(r) r.ApplyAppPathModifier(It.IsAny(Of String))).Returns(Of String)(Function(s) s) 'create httpMockContext using request and response mock Dim mockHttpContext As New Mock(Of HttpContextBase) mockHttpContext.Setup(Function(r) r.Request).Returns(mockRequest.Object) mockHttpContext.Setup(Function(r) r.Response).Returns(mockResponse.Object) Return mockHttpContext.Object End Function
Above function return fake copy of HttpContextBase class.first we have overrides the request for AppRelativeCurrentExecutionFilePath property of HttpRequestBase with user define URL values, and HttpMethod with the Optional GET string value. we have created Mock of HttpResponseBase it just simply return combined url with session id.don't be confuse with this it doesn't make much sense to our testing. and in the last we have just mock HttpContextBase and overrides the property Request,Response with our mocked HttpRequestBase,HttpResponseBase object.
when data is extracted from URL we have to check that extracted values that we expect.for that we have to create function so it can compare the route data with values we expect.
Private Function TestIncomingRouteResult(ByVal rd As RouteData, ByVal controller As String, ByVal action As String, Optional properties As Object = Nothing) As Boolean Dim valCompare As Func(Of String, String, Boolean) = Function(p1 As String, p2 As String) Return (StringComparer.InvariantCultureIgnoreCase.Compare(p1, p2) = 0) End Function Dim result As Boolean = valCompare(rd.Values("controller"), controller) And valCompare(rd.Values("action"), action) If properties IsNot Nothing Then Dim propinfo() As PropertyInfo = properties.GetType.GetProperties For Each pi In propinfo If Not (rd.Values.ContainsKey(pi.Name) And valCompare(rd.Values(pi.Name), pi.GetValue(properties, Nothing))) Then result = False Exit For End If Next End If Return result End Function
In Above code first we check for controller and action values of RouteData is matched with the values that we passed as a parameter. after that we check for the extra parameters that we passed using URL like Query String or id value. any of this comparison get failed function return false and test get failed.
for testing purpose we have created two method. one for check Route should matched and another for checking that route should failed.
Public Sub TestRouteMatch(ByVal url As String, ByVal controller As String, ByVal action As String, Optional routeProperties As Object = Nothing, Optional httpMethod As String = "GET") 'Arrange Dim routes As New RouteCollection MvcApplication.RegisterRoutes(routes) 'Act Dim data As RouteData = routes.GetRouteData(CreateHttpContext(url, httpMethod)) 'Assert Assert.IsNotNull(data) Assert.IsTrue(TestIncomingRouteResult(data, controller, action, routeProperties)) End Sub Public Sub TestRouteFail(ByVal url As String, Optional ByVal httpmethod As String = "GET") 'arrange Dim routes As New RouteCollection MvcApplication.RegisterRoutes(routes) 'Act Dim data As RouteData = routes.GetRouteData(CreateHttpContext(url, httpmethod)) 'Assert Assert.IsTrue(data Is Nothing OrElse data.Route Is Nothing) End Sub
In both of above method first we force MVC to register available routes.next we create mocked HttpContext using URL and HttpMethod and pass it to GetRouteData function of RouteCollection. and we check for the data that is extracted from the URL using method TestIncomingRouteResult.depend on the result of that method Test get Pass or Fail.
Below route definition and testing is just for your reference purpose of how to test routes with above mechanism.because for real testing you have to check route one by one by commenting some other routes.
Public Sub TestIncomingRoutes() TestRouteMatch("~/RouteTest/Index", "RouteTest", "Index") 'Match by R1,R2 TestRouteMatch("~/", "RouteTest", "Index") 'by R2 TestRouteFail("~/RouteTest/Index/Segment") TestRouteFail("~/RouteTest") 'passed if R1 route is not present 'route with url segment TestRouteMatch("~/", "RouteTest", "Index", New With {.id = "someValue"}) 'match by R7 TestRouteMatch("~/RouteTest", "RouteTest", "Index", New With {.id = "somevalue"}) 'match by R7 TestRouteMatch("~/RouteTest/Index", "RouteTest", "Index", New With {.id = "somevalue"}) 'match by R7 TestRouteMatch("~/RouteTest/Index/somevalue", "RouteTest", "Index", New With {.id = "somevalue"}) 'match by R7 TestRouteFail("~/RouteTest/Index/somevalue/somevalue2") 'not match by R7 End Sub 'define routes in global.asax Shared Sub RegisterRoutes(ByVal routes As RouteCollection) routes.IgnoreRoute("{resource}.axd/{*pathInfo}") routes.MapRoute("R2", "{controller}/{action}", New With {.controller = "RouteTest", .action = "Index"}) routes.MapRoute("R1", "{controller}/{action}", New With {.action = "Index"}) routes.MapRoute("R7", "{controller}/{action}/{id}", New With {.controller = "RouteTest", .action = "Index", .id = "somevalue"}) End Sub
0 comments:
Post a Comment
Write your review about this post.