7

私はモッキング フレームワークを初めて使用し、RhinoMocks を使用して MVC アプリ ユニット テストを支援し始めました。

Scott Hanselmann の MVC Mock Helperを使用して、HttpContext のモックを作成しています。私は(しばらくしてから)必要なもののいくつかをうまくモックしましたが、HttpContextのApplicationプロパティに関しては行き詰まりました。

私のアプリケーションでは、オブジェクトをアプリケーションに保存し、次のようにコントローラー内で取得します。

SomeObj foo = (SomeObj)Application["fooKey"];

これは、MVC アプリの Application_Start で作成されます。

UPDATED FOLLOWING FOLLOWING FIRST ANSWER (明確にするための追加コード) 現在、テストセットアップで次のことを行っています。

HttpContextBase mockHttpBase = mocks.FakeHttpContext();
controllerToTest = new SomeController();
mocks.SetFakeControllerContext(controllerToTest);


HttpApplicationStateBase appState = 
    MockRepository.GenerateStub<HttpApplicationStateBase>();

Globals tmpAppGlobals = 
    new Globals();

mockHttpBase.Expect(ctx => ctx.Application).Return(appState);
mockHttpBase.Expect(ctx => ctx.Application[Globals.GlobalsKey]).
    Return(tmpAppGlobals);

私の単体テストのセットアップでは、次のことを行います。

Globals tmpAppGlobals = new Globals();
controllerToTest.ControllerContext.HttpContext.
            Expect(ctx => ctx.Application[Globals.GlobalsKey]).
Return(tmpAppGlobals);

この呼び出しは、Application オブジェクトに対して NullReference 例外をスローします。

私の質問は 2 つあります。

1)これは正しいアプローチですか、それとも設計/アーキテクチャの観点から何か間違ったことをしましたか?

2) なぜこれが機能しないのですか?!

前もって感謝します。

4

2 に答える 2

1

以下をMoqに使用できます。HttpApplication をモックする方法にはしばらく時間がかかりました。appState.Object は戻りメソッドです。

public static HttpContextBase FakeHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new FakeHttpSessionState();
        var server = new Mock<HttpServerUtilityBase>();
        var appState = new Mock<HttpApplicationStateBase>();

        context.Setup(ctx => ctx.Request).Returns(request.Object);
        context.Setup(ctx => ctx.Response).Returns(response.Object);
        context.Setup(ctx => ctx.Session).Returns(session);
        context.Setup(ctx => ctx.Server).Returns(server.Object);
        context.Setup(ctx => ctx.Application).Returns(appState.Object);

        //emulate session (HttpContext.Current.Session) 
        var contx = new HttpContext(new MyApp.NUnit.Tests.Fakes.FakeHttpWorkerRequest());
        contx.Items["AspSession"] = CreateSession();

        HttpContext.Current = contx;

        return context.Object;
    }
于 2010-08-16T22:04:01.277 に答える
1

深く掘り下げなくても、これはほとんど正しいように見えます。

Application プロパティは HttpContextBase で仮想であるため、Rhino からの戻り値を設定できるはずです。Scott Hanselmann の投稿のように HttpContextBase をモックしていると仮定します。

いくつかの考えられる原因は、実際には情報不足からの推測にすぎません。

  • controllerToTest.ControllerContext の戻り値を設定しましたか?
  • その オブジェクトの HttpContext プロパティのリターンを設定しましたか?
  • その オブジェクトのアプリケーション プロパティのリターンを設定しましたか?

私が尋ねる理由は、通常、期待値のセットアップを行うとき、テストの一部として呼び出されるオブジェクトへの参照が既にあるため、呼び出しのようにプロパティ チェーンを実行しないからですcontrollerToTest.ControllerContext.HttpContext. Expect()

編集:

私は問題を見ていると思います、そしてそれはこの部分にあると思います:

Expect(ctx => ctx.Application[Globals.GlobalsKey])

インデクサーがプロパティと同じように機能しない場合でも、プロパティと同じように機能すると想定していると思います。appState実際に行う必要があるのは、次のように、Item プロパティへの呼び出しを受け取るようにオブジェクトに期待を設定することです。

// setup expectations -- assumes some of the expectations and mocks 
// the from original question
mockHttpBase.Expect(ctx => ctx.Application).Return(appState);
appState.Expect(ctx => ctx.Item(Globals.GlobalsKey)).Return(tmpAppGlobals);

// run the test
于 2009-04-01T15:06:58.000 に答える