2009-03-23 28 views
164

Una delle azioni del mio controller, una che viene chiamata in una richiesta Ajax, restituisce un URL al lato client in modo che possa eseguire un reindirizzamento. Sto usando Url.RouteUrl(..) e durante i miei test di unità questo fallisce poiché il parametro Controller.Url non è precompilato.ASP.NET MVC: unità di controllo dei controller che utilizzano UrlHelper

ho provato un sacco di cose, tra gli altri, che tentano di stub UrlHelper (che non è riuscito), creare manualmente un UrlHelper con un RequestContext che ha un stubbed HttpContextBase (che non è riuscito in una chiamata RouteCollection.GetUrlWithApplicationPath).

Ho cercato su Google ma non ho trovato praticamente nulla sull'argomento. Sto facendo qualcosa di incredibilmente stupido usando Url.RouteUrl nell'azione del mio controller? C'è un modo più semplice?

Per renderlo ancora peggio, mi piacerebbe essere in grado di testare l'URL restituito nel mio test di unità - in realtà sono interessato solo a sapere che sta reindirizzando sulla giusta rotta, ma dal momento che sto restituendo un URL invece di una rotta, vorrei controllare l'URL che è stato risolto (ad esempio utilizzando uno stoppato RouteCollection), ma sarò felice di far passare il mio test dall'inizio.

risposta

196

Ecco uno dei miei test (xUnit + MOQ) solo per caso simile (utilizzando Url.RouteUrl nel controllore)

Spero che questo aiuti:

var routes = new RouteCollection(); 
MvcApplication.RegisterRoutes(routes); 

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); 

var controller = new LinkbackController(dbF.Object); 
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller); 
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes); 
+2

Per il momento sono andato con una soluzione in cui ho estratto le chiamate a UrlHelper in modo da poterle intercettare. Grazie per il tuo frammento, tuttavia, mi salverà un sacco di tempo per capire come deridere correttamente una richiesta/risposta/ControllerContext. – efdee

+0

Grazie per la risposta @ eu-ge-ne, mi ha aiutato molto. Ho incluso alcune altre configurazioni di moq per utilizzare un parametro di formcollection utilizzato da UpdateModel – woopstash

+16

+1 eccellente. Anche se un suggerimento: io uso questo come MockHelper e cambio la risposta. Setup per ApplyAppPathModifier a questo: response.Setup (x => x.ApplyAppPathModifier (Moq.It.IsAny ())).Restituisce ((String url) => url); È brutto, ma restituisco l'oggetto serializzato nella forma codificata url, invece di codificare il valore restituito. – eduncan911

12

Questo post potrebbe essere utile se si desidera prendere in giro la classe HttpContextBase.

http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx

+0

Cool, questo mi ha aiutato, anche se ho dovuto aggiungere del codice aggiuntivo al metodo FakeHttpContext per fermare l'helper che esplode: context.Setup (ctx => ctx.Request.ApplicationPath) .Returns ("/ AntiBlowup "); Ho anche rifattorizzato il codice in modo che utilizzi la sintassi più recente di Setup(). Grazie. – RichardOD

2

Costruire fuori la risposta @ eu-ge-ne, che mi ha aiutato molto:

ho avuto un ActionResult che ha fatto un redirect così come era una chiamata UpdateModel con un parametro FormCollection . Per l'UpdateModel() per lavorare ho dovuto aggiungere questo al mio HttpRequestBase deriso:

FormCollection collection = new FormCollection(); 
collection["KeyName"] = "KeyValue"; 

request.Setup(x => x.Form).Returns(collection); 
request.Setup(x => x.QueryString).Returns(new NameValueCollection()); 

Per verificare che l'URL reindirizzato era corretta, è possibile effettuare le seguenti operazioni:

RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult; 
Assert.AreEqual("/Expected/URL", result.Url); 
33

Una implementazione modificata da eu-ge-ne. Questo restituisce un collegamento generato in base ai percorsi definiti nell'applicazione. L'esempio di eu-ge-ne ha sempre restituito una risposta fissa. L'approccio seguente ti consentirà di verificare che l'azione corretta/il controller e le informazioni sul percorso vengano trasmessi a UrlHelper - che è ciò che desideri se stai testando una chiamata a UrlHelper.

+0

Risposta perfetta per me, grazie Steven! – jhilden

Problemi correlati