ASP.NET MVC内のテストコードでも、華麗に使われているMoq.dllを少々使ってみた。こ奴が何者かという事に関しては「まずコードを見ろ!」と言いたいところですが、端的に述べると「単体テスト用のMockを作りやすくするライブラリ」でしょうか?前々からASP.NET MVC内部で眺めては居たのですが、実際使ってみてこいつの便利さを知ってみました。
で、肝心の取得場所ですが、Google Codeに公開されています。こちらからDL可能ですので、Moq.3.1.416.3現在のバイナリをDLしてください。
まず使ってみる
そもそも使い方がさっぱりわからんので、とりあえず使ってみる
[TestMethod()] public void HttpSessionStateBase01() { //NotImplementedExceptionが発生するかのテスト HttpSessionStateBase target = new Mock<HttpSessionStateBase>().Object; //でない!ひゃっほー target.Abandon(); }
とりあえず試してみた。モックを作りたいクラスをMockのジェネリックで指定してインスタンスを生成します(これがモックファクトリー的な物になってるのかな?)。作成したインスタンスに対して、Objectプロパティからモックインスタンスを生成します。
で、この例だとHttpSessionStateBase#Abandonメソッド呼んでますが、通常発生する筈のNotImplementedExceptionが発生しません。
簡単にプロパティを設定してみる
次は単にモックインスタンスを生成するだけでなく、プロパティも設定できるようにしてみます。
[TestMethod()] public void HttpSessionStateBase02() { //メソッドのセット bool expected = true; bool actual; Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>(); Mock<HttpSessionStateBase> mockHttpSession = new Mock<HttpSessionStateBase>(); mockHttpSession.Setup(session => session.IsNewSession).Returns(true); mockHttpContext.Setup(context => context.Session).Returns(mockHttpSession.Object); var httpContext = mockHttpContext.Object; //NewSessionをtrueにする! actual = httpContext.Session.IsNewSession; //ちゃんと帰ってきてる! Assert.AreEqual(expected, actual); }
お次はHttpContextBaseクラス、HttpSessionStateBaseクラスそれぞれのモックを作成し、HttpSessionStateBase#IsNewSessionプロパティにtrueを設定しています。すげー、すげーよ!今まで必死に独自モッククラスを作っていたのが嘘みたいだよ!
インデクサも設定
次にインデクサ系も設定してみた。だいたい以下な感じでモックを生成できます。
[TestMethod()] public void HttpSessionStateBase03() { //メソッドのセット string expected = "Hello Moq Study"; string actual; Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>(); Mock<HttpSessionStateBase> mockHttpSession = new Mock<HttpSessionStateBase>(); mockHttpSession.Setup(session => session["viewData"]).Returns("Hello Moq Study"); mockHttpContext.Setup(context => context.Session).Returns(mockHttpSession.Object); var httpContext = mockHttpContext.Object; actual = httpContext.Session["viewData"] as string; //ちゃんとハッシュ系にも値が仕込まれてる Assert.AreEqual(expected, actual); }
うーん、テラ便利。いざASP.NET系のテストをするとき、インスタンス生成に困るHttpContextBaseやら、HttpSessionStateBaseやらのインスタンスをこうも簡単に作れるとは…。
ユーザ認証
最後にユーザ認証を試してみる。
[TestMethod()] public void IIdentity01() { Mock<HttpSessionStateBase> mockHttpSession = new Mock<HttpSessionStateBase>(); Mock<IPrincipal> mockIPrincipal = new Mock<IPrincipal>(); Mock<IIdentity> mockIdentity = new Mock<IIdentity>(); mockIdentity.Setup(identity => identity.IsAuthenticated).Returns(true); mockIdentity.Setup(identity => identity.Name).Returns("normalian"); mockIPrincipal.Setup(principal => principal.Identity).Returns(mockIdentity.Object); //mockIPrincipal.Setup(principal => principal.IsInRole ).Returns( name => "normalian" == name ); //ここは無理 var User = mockIPrincipal.Object; //認証されて、ユーザ名も設定済み Assert.AreEqual(true, User.Identity.IsAuthenticated); Assert.AreEqual("normalian", User.Identity.Name); }
User認証の設定、ユーザオブジェクトのユーザ名もきっちり設定されてる!これでもうASP.NETだろうが、Silverlightだろうが怖くないっす!!