ASP.NET MVC: UrlHelper kullanan birim sınama denetleyicileri


170

Denetleyici eylemlerimden biri, bir Ajax isteğinde çağrılan biri, yönlendirme yapabilmesi için istemci tarafına bir URL döndürüyor. Kullanıyorum Url.RouteUrl(..)ve birim testleri sırasında Controller.Urlparametre önceden doldurulmadığından bu başarısız olur .

Bir sürü şey denedim, diğerleri arasında saplama UrlHelper(başarısız), el UrlHelperile RequestContextstubbed HttpContextBase(olan bir RouteCollection.GetUrlWithApplicationPathçağrı başarısız) olan bir ile oluşturma .

Google'da arama yaptım ancak konu hakkında neredeyse hiçbir şey bulamadım. Url.RouteUrlDenetleyici eylemimde inanılmaz derecede aptalca bir şey mi kullanıyorum ? Daha kolay bir yol var mı?

Daha da kötüsü, birim URL'mde döndürülen URL'yi test etmek istiyorum - aslında sadece doğru yola yönlendirildiğini bilmekle ilgileniyorum, ancak bir URL yerine bir URL döndürdüğüm için , çözümlenmiş URL'yi kontrol etmek istiyorum (örn. bir stubbed kullanarak RouteCollection) - ancak başlamak için test geçerken mutlu olurum.

Yanıtlar:


202

İşte benzer durum için testlerimden biri (xUnit + Moq) (denetleyicide Url.RouteUrl kullanarak)

Bu yardımcı olur umarım:

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
Şimdilik, onları arayabilmem için UrlHelper çağrılarını soyutladığım bir çözümle gittim. Ancak snippet'iniz için teşekkürler, bir İstek / Yanıt / Denetleyici Bağlamını nasıl doğru bir şekilde alay edeceğimi anlamak bana çok zaman kazandıracak.
efdee

@ Eu-ge-ne cevabı için teşekkürler, bu da bana çok yardımcı oldu. UpdateModel tarafından kullanılan bir formcollection parametresini kullanmak için bazı adedi kurulumları ekledim
jebcrum

16
+1 mükemmel. Bir ipucu olmasına rağmen: Bunu bir MockHelper olarak kullanıyorum ve yanıtı değiştiriyorum. ) => url); Çirkin, ama döndürülen değeri hardcoding yerine seri hale getirilmiş nesneyi url kodlu biçimde geri alıyorum.
eduncan911

Bu kısmen benim için çalışıyor. Denetleyici / Eylem yerine Denetleyici /'yi neden aldığım konusunda bir fikrin var mı? Testim başarısız oluyor çünkü aynı değiller ve yine de aynı yönlendirme değerlerini kaydediyorum. Çok tuhaf ...
Nick

3
ApplyAppPathModifierBölüm UrlHelper için kritik bit
Chris S

37

Eu-ge-ne tarafından değiştirilmiş bir uygulama. Bu, uygulamada tanımlanan yollara dayalı olarak oluşturulmuş bir bağlantı döndürür. eu-ge-ne örneği her zaman sabit bir yanıt verdi. Aşağıdaki yaklaşım, doğru eylem / denetleyici ve rota bilgilerinin UrlHelper'a iletildiğini test etmenize izin verecektir - bu, UrlHelper çağrısını test ediyorsanız istediğiniz şeydir.

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

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

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

response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);

context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var helper = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);

12

HttpContextBase sınıfını alay etmek istiyorsanız bu yazı yararlı olabilir.

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


Cool, bu yardımcı oldu, ancak yardımcı üfleme kadar durdurmak için FakeHttpContext yöntemine bazı ekstra kod eklemek zorunda kaldı: context.Setup (ctx => ctx.Request.ApplicationPath) .Returns ("/ AntiBlowup"); Daha yeni Setup () sözdizimini kullanması için de kodu yeniden düzenledim. Teşekkürler.
RichardOD

2

@ Eu-ge-ne'nin yanıtı bana çok yardımcı olan cevabı kaldırmak:

Bir yönlendirme yaptım yanı sıra FormCollection parametresi ile bir UpdateModel çağrısı vardı bir ActionResult vardı. UpdateModel () çalışması için bu benim Mocked HttpRequestBase eklemek zorunda kaldı:

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

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

Yeniden yönlendirilen URL'nin doğru olup olmadığını test etmek için aşağıdakileri yapabilirsiniz:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.