Moqを使用してASP.NET MVCのHttpContextをモックするにはどうすればよいですか?


101
[TestMethod]
public void Home_Message_Display_Unknown_User_when_coockie_does_not_exist()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    context
        .Setup(c => c.Request)
        .Returns(request.Object);
    HomeController controller = new HomeController();

    controller.HttpContext = context; //Here I am getting an error (read only).
    ...
 }

私の基本コントローラーには、このrequestContextを取得するInitializeのオーバーライドがあります。私はこれを伝えようとしていますが、何か正しいことをしていません。

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
}

Moqを使用したRequestContextとHttpContextのモックに関する詳細情報はどこで入手できますか?私はクッキーと一般的なコンテキストを模倣しようとしています。

回答:


61

HttpContextは読み取り専用ですが、実際には、設定可能なControllerContextから派生しています。

 controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );

これは、コントローラーにモックHttpContextを設定できるようにすることで機能しました。
Joel Malone

39

リクエストとレスポンスを作成し、両方をHttpContextに配置します。

HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);

問題は* Baseクラス、つまりHttpRequestではなくHttpRequestBaseについてです-なぜ両方が自分自身に必要なのか、そしてそれらが「封印」されていることにさらに迷惑をかけるのかわかりません。LogonUserIdentityを設定する方法はありません:(
Chris Kimpton

彼らが私のリファレンスをマーシャリングした場合でも、リモーティングを介してそれが可能であるため、問題にはなりません。
0100110010101

1
@ChrisKimpton:最後の手段として、常に反省があります ;-)
Oliver

これは、次のようにコントローラに接続するときに機能します。controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock)、new RouteData()、controller);
Andreas Vendel 14年

はい。実際に.LogonUserIdentityを設定できます-_request.Setup(n => n.LogonUserIdentity).Returns((WindowsIdentity.GetCurrent));
KevinDeus 2014年

12

ユーザー0100110010101に感謝します。

それは私のために働き、ここで私は以下のコードのテストケースを書いている間に問題がありました:

 var currentUrl = Request.Url.AbsoluteUri;

そして、これが問題を解決した行です

HomeController controller = new HomeController();
//Mock Request.Url.AbsoluteUri 
HttpRequest httpRequest = new HttpRequest("", "http://mySomething", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), new RouteData(), controller);

他の人に役立つかもしれません。


私はHttpRequestタイプを使用できないようです-それは今何か他のものですか?
Vincent Buscarello

1
HttpRequestのすべてのフィールドは不変であるため、これは役に立ちません
A br

6

これを設定する方法の例を次に示します。UnitTestsのHttpContext HttpRequestおよびHttpResponseのモック(Moqを使用)

このモッキングクラスの使用を簡単にするのに役立つ拡張メソッドに注意してください。

var mockHttpContext = new API_Moq_HttpContext();

var httpContext = mockHttpContext.httpContext();

httpContext.request_Write("<html><body>".line()); 
httpContext.request_Write("   this is a web page".line());  
httpContext.request_Write("</body></html>"); 

return httpContext.request_Read();

以下は、moqを使用して単体テストを記述し、HttpModuleが期待どおりに動作していることを確認する方法の例です。Moqを使用してHttpRequestをラップするHttpModuleの単体テスト

更新:このAPIはリファクタリングされました


リンクが壊れています
Hades

5

ControllerContextを使用して偽のアプリケーションパスを渡す方法を次に示します。

[TestClass]
public class ClassTest
{
    private Mock<ControllerContext> mockControllerContext;
    private HomeController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        mockControllerContext = new Mock<ControllerContext>();
        sut = new HomeController();
    }
    [TestCleanup]
    public void TestCleanup()
    {
        sut.Dispose();
        mockControllerContext = null;
    }
    [TestMethod]
    public void Index_Should_Return_Default_View()
    {

        // Expectations
        mockControllerContext.SetupGet(x => x.HttpContext.Request.ApplicationPath)
            .Returns("/foo.com");
        sut.ControllerContext = mockControllerContext.Object;

        // Act
        var failure = sut.Index();

        // Assert
        Assert.IsInstanceOfType(failure, typeof(ViewResult), "Index() did not return expected ViewResult.");
    }
}

1
なぜ偽のアプリケーションパスを渡す必要があるのですか?
the_law

MVCコードはそれを実行し、そこになければnull例外をスローします。
ジョシュアラミレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.