Unit Testing registered routes in MVC

When you have a lot of routes in a MVC application, it could be very tricky to get things right. It is always helpful to have unit testings against the registered routes. Especially when you make changes and it makes sure you will not break anything that already exists. I will show you a couple of examples how do I write unit testings for my routes.

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "PageRoute", // Route name
                "Page/{action}/{id}", // URL with parameters
                new { controller = "Home", id = UrlParameter.Optional } // Parameter defaults
            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

            routes.MapRoute(
                "ErrorRoute", // Route name
                "{*anything}",
                new { controller = "Home", action = "Missing"} // Parameter defaults
            );

        }

In the code snippet, I have registered 3 routes. “PageRoute”, “Default” and “ErrorRoute”.

Now let’s create a unit testing project, and use Moq as the mock framework. (You can also use Rhino Mocks). Don’t forget to reference you mvc application then we are ready to write some tests.

    [TestClass]
    public class HomeControllerTest
    {
        [TestMethod]
        public void DefaultRouteTest()
        {
            var routes = new RouteCollection();
            MvcApplication.RegisterRoutes(routes);

            var context = new Mock<HttpContextBase>();
            context.Setup(p => p.Request.AppRelativeCurrentExecutionFilePath).Returns("~/");
            var routeData = routes.GetRouteData(context.Object);

            Assert.AreEqual(((Route)routeData.Route).Url, "{controller}/{action}/{id}");
            Assert.AreEqual("Home", routeData.Values["controller"], "default controller is home controller");
            Assert.AreEqual("Index", routeData.Values["action"], "default action");
        }

        [TestMethod]
        public void PageRouteTest()
        {
            var routes = new RouteCollection();
            MvcApplication.RegisterRoutes(routes);

            var context = new Mock<HttpContextBase>();
            context.Setup(p => p.Request.AppRelativeCurrentExecutionFilePath).Returns("~/Page/About");
            var routeData = routes.GetRouteData(context.Object);

            Assert.AreEqual(((Route)routeData.Route).Url, "Page/{action}/{id}");
            Assert.AreEqual("Home", routeData.Values["controller"], "default controller is home controller");
            Assert.AreEqual("About", routeData.Values["action"], "default action");
        }

        [TestMethod]
        public void ErrorRouteTest()
        {
            var routes = new RouteCollection();
            MvcApplication.RegisterRoutes(routes);

            var context = new Mock<HttpContextBase>();
            context.Setup(p => p.Request.AppRelativeCurrentExecutionFilePath).Returns("~/DDA/asd/asd/asd/WhereIsIt");
            var routeData = routes.GetRouteData(context.Object);

            Assert.AreEqual(((Route)routeData.Route).Url, "{*anything}");
            Assert.AreEqual("Home", routeData.Values["controller"], "default controller is home controller");
            Assert.AreEqual("Missing", routeData.Values["action"], "default action");

        }

    }

When writing the unit tests, you will need to mock HttpContextBase and setup the Request.AppRelativeCurrentExecutionFilePath and make it returns your targeting url. Pass the context to your route collection. You can use Assert to test what route is returned in the RouteData.

Advertisements