1

Now UrlHelper has been made friendly for unit testing I wanted to replace old test code with a mocked version. However I can't seem to get T4MVC's Action extension method to actually call the mocked method, it keeps hitting UrlHelper's method according to the stack trace.

I've tried setting the Url property on the controller to be a Moq object and also subclassed UrlHelper. I've verified both are getting called by debugging the method.

Just using strict mocking to try and generate the right exception:

_url = new Mock<UrlHelper>(MockBehavior.Strict);
_controller.Url = _url.Object;
_controller.Url.Action(MVC.Home.Index()); //Should throw UrlHelper.RouteUrl not mocked exception

Instead I get:

System.ArgumentNullException : Value cannot be null.
Parameter name: routeCollection    
at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) 
at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) 
at System.Web.Mvc.UrlHelper.RouteUrl(String routeName, RouteValueDictionary routeValues, String protocol, String hostName) 
at System.Web.Mvc.T4Extensions.Action(UrlHelper urlHelper, ActionResult result, String protocol, String hostName)

The code is going straight from T4MVCExtensions to UrlHelper.

If I copy the code from the T4MVC extension method into a new extension method in the web project the mocked UrlHelper does get called and everything works as expected.

public static class UrlExtensions
    {
        public static string Action(this UrlHelper urlHelper, ActionResult result)
        {
            return urlHelper.RouteUrl(null, result.GetRouteValueDictionary(), result.GetT4MVCResult().Protocol, null);
        }
    }

Have I missed something fundamental about extension methods? I can't work out what is going on which might cause the extension method to be using the parent class implementation. For reference I'm using Resharper 8.1 to run the tests, Moq 4.2 and NUnit 2.6.4 and T4MVCExtensions 3.11.0.

Chris
  • 2,447
  • 1
  • 21
  • 27
  • 2
    How certain are you that the version of `UrlHelper` you're actually running against has that as a virtual method? Do you know which version T4MVCExtensions was built against? – Jon Skeet Jan 16 '15 at 17:58
  • Yes, @JonSkeet may be correct here. At runtime, it doesn't matter, because web.config unifies things via binding redirects. But when running tests, this doesn't happen unless you were to create a {app}.exe.config for whichever exe it's running under (probably devenv.exe). – David Ebbo Jan 22 '15 at 05:43
  • Looks like it, many thanks to @JonSkeet for reminding me something I'd long forgotten about virtual methods! – Chris Jan 22 '15 at 09:51

0 Answers0