I'm encountering a strange behaviour when unit testing controller. I'm using some extension methods for building Url.Action and all works well when runing code in production but the unit test fails. In fact my custom Url.Action helper is using the method :
System.Web.Routing.RouteCollection.GetVirtualPathData
the exact line is :
VirtualPathData localizedPathData = HtmlExtensions.GetVirtualPathData(newRouteTable, Url.RequestContext, routingValues);
string url = localizedPathData.VirtualPath.ToLower();
The problem is that while unit testing the localizedPathData.VirtualPath is an empty string instead the url for the route like in the production code. The routingValues contains three keys "area", "controller", "action" with related values to the controller/action that I would like to have a url generated to. What's strange is 开发者_开发知识库that localizedPathData.Route property contains the correct route ! So why the localizedPathData.VirtualPath is an empty string ?
I tried with GetVirtualPathForArea but the result is the same.
I'm mocking with MvcContrib TestControllerBuilder.
The sample code is here :
// Arrange
var loginInput = new LoginInput { EmailAddress = "test@test.fr", Password = "test", RememberMe = false };
new RouteConfigurator().RegisterRoutes(() => new ResumeAreaRegistration().RegisterArea(new AreaRegistrationContext("Resume", RouteTable.Routes)));
var testControllerBuilder = new TestControllerBuilder();
var loginController = testControllerBuilder.CreateController<LoginController>();
loginController.Url = new UrlHelper(new RequestContext(loginController.HttpContext, new RouteData()), RouteTable.Routes);
loginController.Url.RequestContext.RouteData.Values.Add("area","Resume");
loginController.Url.RequestContext.RouteData.Values.Add("culture","en-US");
const string defaultUrl = "/Dashboard";
// act
var result = loginController.Index(loginInput, null);
// assert
result.ShouldNotBeNull();
result.AssertHttpRedirect().Url.ShouldBe(defaultUrl);
Maybe I'm missing something ? Something I forgot about ?
Thank you in advance for your help.
I was looking with Reflector and found that the reason it isn't working is that internally the RouteCollection object calls the ApplyAppPathModifier method on HttpResponseBase. The fix would be to setup an expectation on the ApplyAppPathModifier method of the HttpResponseBase mock to just return the value that is passed into it. If you are using Rhino Mocks, then it would look like this:
loginController.HttpContext.Response.Stub(x => x.ApplyAppPathModifier(Arg<string>.Is.Anything)).IgnoreArguments().Do((Func<string, string>)((arg) => { return arg; }));
精彩评论