ASP.NET MVC:UrlHelperを使用するユニットテストコントローラー


170

私のコントローラーアクションの1つであるAjaxリクエストで呼び出されるアクションは、リダイレクトを実行できるようにクライアント側にURLを返します。私は使用Url.RouteUrl(..)していController.Urlますが、ユニットテスト中にパラメーターが事前入力されていないため、これは失敗します。

私は、スタブにしようと他の人の間で、多くのことを試してみましたUrlHelper手動で作成し、(失敗した)UrlHelperRequestContextスタブ持っているHttpContextBase(上の失敗したRouteCollection.GetUrlWithApplicationPathコール)。

私はGoogleを検索しましたが、事実上何も見つかりませんでした。Url.RouteUrl私のコントローラーアクションで信じられないほど愚かなことをしていますか?もっと簡単な方法はありますか?

さらに悪いことに、ユニットテストで返されたURLをテストできるようにしたいのですが、実際には、正しいルートにリダイレクトされていることだけを知りたいのですが、ルート、解決されるURLを制御したいと思います(例:stubbedを使用してRouteCollection)-しかし、最初にテストに合格させていただきます。

回答:


202

これは、同様のケースのための私のテスト(xUnit + Moq)の1つです(コントローラーでUrl.RouteUrlを使用)

お役に立てれば:

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
とりあえず、私はUrlHelperへの呼び出しを抽象化してそれらを傍受できるソリューションを使いました。ただし、スニペットをお寄せいただきありがとうございます。これにより、リクエスト/レスポンス/コントローラコンテキストを正しくモックする方法を理解するのにかなりの時間を節約できます。
efdee 2009年

回答@ eu-ge-neに感謝します。それも私を助けてくれました。UpdateModelで使用されるformcollectionパラメーターを使用するためにいくつかのmoqセットアップを含めました
jebcrum '10

16
+1すばらしい。ヒントですが、これをMockHelperとして使用して、ApplyAppPathModifierのresponse.Setupを次のように変更します:response.Setup(x => x.ApplyAppPathModifier(Moq.It.IsAny <String>()))。Returns((String url )=> url); 醜いですが、返された値をハードコーディングするのではなく、URLエンコードされた形式でシリアル化されたオブジェクトを取得します。
eduncan911

それは部分的に私のために働きます。コントローラー/アクションではなくコントローラー/を取得する理由はありますか?テストはまったく同じではないため、失敗しましたが、同じルーティング値を登録しています。非常に奇妙な...
Nick

3
ApplyAppPathModifier一部はUrlHelperのための重要なビットである
クリス・S

37

eu-ge-neからの変更された実装。これは、アプリケーションで定義されたルートに基づいて生成されたリンクを返します。eu-ge-neの例は常に固定応答を返しました。以下のアプローチでは、正しいアクション/コントローラーおよびルート情報がUrlHelperに渡されていることをテストできます。これは、UrlHelperへの呼び出しをテストする場合に必要です。

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クラスをモックしたい場合に役立ちます。

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


ヘルパーが爆発するのを防ぐために、メソッドFakeHttpContextにいくつかの追加コードを追加する必要がありましたが、これは私を助けてくれました。また、新しいSetup()構文を使用するようにコードをリファクタリングしました。ありがとう。
RichardOD 2009

2

@ eu-ge-neの答えを基にして、私を大いに助けました。

リダイレクトを行うActionResultと、FormCollectionパラメーターを使用したUpdateModel呼び出しがありました。UpdateModel()を機能させるには、これをMocked HttpRequestBaseに追加する必要がありました。

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

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

リダイレクトされたURLが正しいことをテストするには、次のようにします。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.