2013-03-06 18 views
10

Uso le librerie NUnit e Moq per il test dell'unità. Ho bisogno di simulare sovraccarico Url.Action(string, string, object, string), perché l'azione del mio controller lo usa per get an absolute url of an Action.Mocking Controller.Url.Action (stringa, stringa, oggetto, stringa) in ASP.NET MVC

La mia prova per la società (guarda 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; 
    } 
} 

E sulla linea di

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

ottengo un'eccezione

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) 

E 'strano per me che controller.Url.Action("TestAction") funzioni correttamente, ma controller.Url.Action("TestAction", null, null, "http") no.

P.S. MvcMoqHelpers.FakeHttpContext() è da here, forse aiuterà a rispondere alla domanda.

Quindi la domanda è: come posso ottenere Url.Action (stringa, stringa, oggetto, stringa) deriso?

Grazie.

+0

E l'URL in context.Request.SetupRequestUrl (url)? – Nenad

+0

Possibile duplicato di [ASP.NET MVC: Mock controller.Url.Action] (https://stackoverflow.com/questions/1367616/asp-net-mvc-mock-controller-url-action) –

risposta

10

È necessario impostare Request.Url, e si dispone di quel pezzo di codice nel tutorial che hai fornito:

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

ragione è - nella vostra sovraccarico Url.Action non si fornisce il nome host e il protocollo, così MVC tenta di estrarre tali valori da Request.Url

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

Sembra che tu abbia ragione. Ho modificato il metodo 'public static void SetupRequestUrl (questa richiesta HttpRequestBase, stringa url)' da quel tutorial aggiungendo la riga 'mock.Setup (req => req.Url) .Returns (nuovo Uri (nuovo Uri (" http: // localhost/"), url));' E sembra funzionare ora se chiamo sovraccarico 'FakeHttpContext (string url)'. Non sono sicuro che sia il modo più semplice per risolvere il problema, ma in ogni caso accetto la tua risposta. Grazie. – kasitan