Routing / Unit Testing Controller in MVC4

Purpose: to verify that the given url returns the specified controller function.

In the process, I broke into the routing system, and I can’t understand how to test the routes (or, for that matter, find the controller that matches the route: - /).

Example code that does not work:

[Test] public void kick_the_tires() { var rc = new RouteCollection(); Infrastructure.RouteRegistry.RegisterRoutes(rc); // get the route corresponding to name. var got = rc["name"]; var expected = //What? foo is an internal type that can't be instantiated. Assert.AreEqual(foo, frob); } 

edit: using a related blog post from Simon for the stub class.

 [TestCase("/", "~/", "Home", "Index")] [TestCase("/", "api/command", "Other", "command")] internal void stub_mocker(string apppath, string route, string expected_controller,\ string expected_action) { var rc = new RouteCollection(); Infrastructure.RouteRegistry.RegisterRoutes(rc); var httpmock = new StubHttpContextForRouting( appPath: apppath, requestUrl: route); // this always returns null for everything but the Index case. var routeData = rc.GetRouteData(httpmock); var controller = routeData.Values["controller"]; var action = routeData.Values["action"]; Assert.AreEqual(expected_controller, controller); Assert.AreEqual(expected_action, action); } 
+4
source share
2 answers

All that you are testing now is if the routes are added to the collection by accessing it by the name of the route, and not if the expected route returns with the virtual path. You need to get the route data returned by the RouteCollection with the HttpContext.

The best way is to use a layout or stub for the HttpContext (or HttpContextBase) and call the RouteCollection GetRouteData (HttpContextBase) method and check the route data.

Here is a good example of this on Brad Wilson's blog: http://bradwilson.typepad.com/blog/2010/07/testing-routing-and-url-generation-in-aspnet-mvc.html

Edit: you cannot get a controller instance from RouteData itself. However, RouteData should provide you with enough information to find out which controller will be created. For example, if you have a controller with MyProject.Controllers.HomeController with a Home action, this should be true in your test (using xUnit and Moq):

 // Prepare var context = new Mock<HttpContextBase>(); var request = new Mock<HttpRequestBase>(); var response = new Mock<HttpResponseBase>(); var session = new Mock<HttpSessionStateBase>(); var server = new Mock<HttpServerUtilityBase>(); context.SetupGet(c => c.Request).Returns(request.Object); context.SetupGet(c => c.Response).Returns(response.Object); context.SetupGet(c => c.Session).Returns(session.Object); context.SetupGet(c => c.Server).Returns(server.Object); request.SetupGet(r => r.HttpMethod).Returns("GET"); request.SetupGet(r => r.PathInfo).Returns(String.Empty); request.SetupGet(r => r.AppRelativeCurrentExecutionFilePath).Returns("~/Home"); var expectedHandler = typeof (HomeController).GetMethod("Index", Type.EmptyTypes); var data = RouteTable.Routes.GetRouteData(context.Object); Assert.NotNull(data); var handler = (MethodInfo) data.DataTokens["actionMethod"]; Assert.Equal(expectedHandler, handler); 
+4
source

I had good experience with MVCContrib Testhelper

Take a look at this testhelper test.

Saves a lot of trouble around stubbing HttpContext etc.

Also, if you are on MVC4, check out this Nuget package , which is fork for MVC4.

+1
source

Source: https://habr.com/ru/post/1487975/


All Articles