2013-03-06 10 views
10

Ich verwende NUnit und Moq Bibliotheken für Komponententests. Ich muss mock überladen Url.Action(string, string, object, string), weil die Aktion meines Controllers es zu get an absolute url of an Action verwendet.Mocking Controller.Url.Action (Zeichenfolge, Zeichenfolge, Objekt, Zeichenfolge) in ASP.NET MVC

jetzt Mein Versuch (siehe MockUrlAction Test):

[TestFixture] 
public class ControllerTests 
{ 
    [Test] 
    public void MockUrlAction() 
    { 
     var controller = new TestController(); 

     controller.Url = new UrlHelper(new RequestContext(MvcMoqHelpers.FakeHttpContext(), new RouteData()), GetRouteCollection()); 

     // it works 
     Assert.AreEqual("/PathToAction", controller.Url.Action("TestAction")); 

     // but it doesn't work 
     Assert.AreEqual("http://example.com/PathToAction", controller.Url.Action("TestAction", null, null, "http")); 
    } 

    private RouteCollection GetRouteCollection() 
    { 
     BundleTable.MapPathMethod = MapBundleItemPath; 
     var routes = new RouteCollection(); 
     RouteConfig.RegisterRoutes(routes); 

     var adminArea = new AdminAreaRegistration(); 
     var adminAreaRegistrationContext = new AreaRegistrationContext(adminArea.AreaName, routes); 
     adminArea.RegisterArea(adminAreaRegistrationContext); 

     return routes; 
    } 
} 

public static class MvcMoqHelpers 
{ 
    public static HttpContextBase FakeHttpContext() 
    { 
     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>(); 

     request.Setup(r => r.AppRelativeCurrentExecutionFilePath).Returns("/"); 
     request.Setup(r => r.ApplicationPath).Returns("/"); 
     response.Setup(s => s.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(s => s); 

     context.Setup(ctx => ctx.Request).Returns(request.Object); 
     context.Setup(ctx => ctx.Response).Returns(response.Object); 
     context.Setup(ctx => ctx.Session).Returns(session.Object); 
     context.Setup(ctx => ctx.Server).Returns(server.Object); 

     return context.Object; 
    } 
} 

Und an der Linie

Assert.AreEqual("http://example.com/PathToAction", controller.Url.Action("TestAction", null, null, "http")); 

ich eine Ausnahme

bekommen für mich
System.NullReferenceException : Object reference not set to an instance of an object. 
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.Action(String actionName, String controllerName, Object routeValues, String protocol) 

Es ist seltsam dass controller.Url.Action("TestAction") funktioniert gut, aber controller.Url.Action("TestAction", null, null, "http") nicht.

P.S. MvcMoqHelpers.FakeHttpContext() ist von here, vielleicht wird es helfen, die Frage zu beantworten.

Also die Frage ist: Wie bekomme ich Url.Action (String, String, Objekt, String) verspottet?

Danke.

+0

Was ist mit URL in context.Request.SetupRequestUrl (URL)? – Nenad

+0

Mögliches Duplikat von [ASP.NET MVC: Mock controller.Url.Action] (https://stackoverflow.com/questions/1367616/asp-net-mvc-mock-controller-url-action) –

Antwort

10

Sie haben Request.Url zu setzen, und Sie haben das Stück Code in Tutorial, das Ihnen zur Verfügung gestellt:

public static HttpContextBase FakeHttpContext(string url) 
{ 
    HttpContextBase context = FakeHttpContext(); 
    context.Request.SetupRequestUrl(url); 
    return context; 
} 

Grund ist - in Ihrem Url.Action Überlastung Sie bieten keine Hostnamen und Protokoll, so MVC versucht, diese Werte aus Request.Url zu extrahieren

if (!String.IsNullOrEmpty(protocol) || !String.IsNullOrEmpty(hostName)) 
{ 
    Uri requestUrl = requestContext.HttpContext.Request.Url; 
    protocol = (!String.IsNullOrEmpty(protocol)) ? protocol : Uri.UriSchemeHttp; 
    hostName = (!String.IsNullOrEmpty(hostName)) ? hostName : requestUrl.Host; 
+0

Scheint, dass Sie Recht haben. Ich habe die Methode 'public static void SetupRequestUrl (diese HttpRequestBase-Anfrage, string url)' aus diesem Tutorial geändert, indem ich die Zeile 'mock.Setup (req => req.Url) hinzugefügt habe.Returns (new Uri (" http: // localhost/"), url));' Und es scheint jetzt zu funktionieren, wenn ich 'FakeHttpContext (string url)' überladen rufe. Ich bin mir nicht sicher, ob es der einfachste Weg ist, das zu beheben, aber ich akzeptiere deine Antwort. Vielen Dank. – kasitan