normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Moq.dll on ASP.NET MVC その2

先日Moq.dllをASP.NET MVCの開発で試しましたが、Controllerのメソッド実行時にnullが帰ってきてテストがうまくできないという問題がありました。
結論から言うと私のコードが間違っていまして、以下のコードに直したところ、まったく問題なく元気に動作しました。

[TestMethod()]
public void 購入してないユーザがEmptyビューに飛ぶTest01()
{
    //Redirectされる先のAction名
    string expected = "Empty";
    string actual;
    var controller = new BuyHistoryController(new TestOrderRepository());

    //モック系の作成
    var mockControllerContext = new Mock<ControllerContext>();
    var mockHttpContextBase = new Mock<HttpContextBase>();
    var mockIdentity = new Mock<IIdentity>();
    var mockPrincipal = new Mock<IPrincipal>();

    //ユーザ情報の設定&httpContextオブジェクトの作成
    mockIdentity.Setup(identity => identity.IsAuthenticated).Returns(true);
    mockIdentity.Setup(identity => identity.Name).Returns("購入してないユーザ");
    mockPrincipal.Setup(principal => principal.Identity).Returns(mockIdentity.Object);
    mockHttpContextBase.Setup(httpContextBase => httpContextBase.User)
        .Returns(mockPrincipal.Object);
    mockControllerContext.Setup(controllerContext => controllerContext.HttpContext)
        .Returns(mockHttpContextBase.Object);

    //コントローラ生成            
    controller.ControllerContext = mockControllerContext.Object;

    //テスト実行(リダイレクト結果が返ってくる)
    RedirectToRouteResult result = controller.Index() as RedirectToRouteResult;
    //テスト実行(次に実行されるアクションを取得)
    actual = result.RouteValues["action"] as string;
    Assert.AreEqual(expected, actual);
}

何が間違っていたかというと、前回のコードでは以下の部分が間違っていました。

var mockBuyHistoryController = new Mock<BuyHistoryController>(new TestOrderRepository());

上記のコードでは、テスト対象クラスのモックを作ってしまってるんですね…。これでは、そもそも単体テストにならないと気付いて自分の知識不足にがっかり…orz
その辺りを直して、再度テストコードとして見直したのが上記のコードとなります。

2009/09/13 追記

上記のコードではまった主な理由として、ステップイン実行した場合にHomeController#Index()メソッド内を実行していた事が原因です。id:masa-k さんが仰る通り、Moq.dllの作り次第なのですが、ライブラリの仕様を押さえずに軽々しく使うとはまってしまいますね・・・。