• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 674
  • Last Modified:

How to unit test a controller that makes a call to Url.GetUrl

I have the following action in my controller that I want to unit test:
        // Returns the ReferralType info along with the keys needed to find duplicate referrals for the selected Referral Type
        public JsonResult getURL(string actionName, string controllerName, string routeVals = null)
        {
            string url = "";

            if (routeVals == null || routeVals == "")
            {
                url = Url.RouteUrl(actionName, controllerName);
                
            }
            else
            {
                url = Url.Action(actionName, controllerName, new { id = routeVals });
            }

            return Json(url, JsonRequestBehavior.AllowGet);
        }

  

Open in new window


I created the following Unit Test:
        [TestMethod]
        public void getURL_Returns_URL_With_No_Parameters_When_RouteValues_Is_Null()
        {
            // Arrange
            var routes = new RouteCollection();
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
            request.SetupGet(x => x.ApplicationPath).Returns("/");
            request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
            request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

            var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
            response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");

            var context = new Mock<HttpContextBase>(MockBehavior.Strict);
            context.SetupGet(x => x.Request).Returns(request.Object);
            context.SetupGet(x => x.Response).Returns(response.Object);

            InMemoryReferralsModelContainterRepository repository = imr.PopulateInMemoryRepository();

            var mockRequestProcessLogic = new Mock<RequestProcessLogic>(repository, new EmployeeProfileRecord(epimr));

            var controller = new RequestProcessController(repository, context.Object, mockRequestProcessLogic.Object);
            controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
            controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);

            // Act
            var result = controller.getURL("Index", "Home");

            // Assert
            Assert.AreEqual("/Home/Index", result.Data);
        }

Open in new window


The test fails because the getUrl action throws the following error:

A route named "Index" could not be found in the route collection.
Parameter name: name

The RequestProcessController does not have an Index method but the HomeController does.  Can someone point out what I am doing wrong in my Unit Test that is causing the error?

Any help is greatly appreciated!
0
dyarosh
Asked:
dyarosh
1 Solution
 
MogalManicCommented:
I think this should help you:  http://icanmakethiswork.blogspot.com/2013/02/unit-testing-mvc-controllers-mocking.html

The only other choice would be to create an "adapter pattern" interface for the URLHelper class.  The default implementation would map to the System.Web.Mvc.UrlHelper class.  Then in the unit test the default could be replaced with a mock implementation of the interface.
0
 
dyaroshAuthor Commented:
Thank you.  I was able to use the solution with some minor modifications.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now