ASP.NET MVC3でフィルタをテストする

ASP.NET MVC3に限らずWebシステムではフィルタを利用することが多いと思いますが、フィルタをテストする際にネックになってくるのがSession変数などの扱いです。これまではどうにもうまく扱うことができずテストが書けないでいたのですが、調べてみると結構便利なツールがありましたので早速利用してみました。

利用方法はファイルをダウンロードして解凍後、MvcContrib.TestHelper.dll を参照するだけですなのでとても簡単です。 (TestHelper以外にもユーティリティがあるようですね。)

テストでどのように利用するかについてはこちらにサンプルがあります。

http://mvccontrib.codeplex.com/wikipage?title=TestHelper&referringTitle=Documentation#Examples

ということで、サンプルを元に例外を集約するフィルタを元に試してみました。例外処理フィルタがテスト対象のフィルタです。

/// <summary>
/// 例外処理フィルタ
/// </summary>
public class ExceptionLoggerAttribute:FilterAttribute,IExceptionFilter
{
    private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    #region Implementation of IExceptionFilter

    public void OnException(ExceptionContext filterContext)
    {
        var ctx = filterContext.Controller.ControllerContext.HttpContext;

        string loginId="";
        if(ctx.Session[ControllerConst.UserInfoIdSessionName]!=null)
        {
            loginId = ctx.Session[ControllerConst.UserInfoIdSessionName].ToString();
        }

        var s =
            string.Format("Exception is thrownd [login Id >> {0}] nError Message:{1}nStack Trace:{2}nInnerException Message:{3}",
                          loginId, filterContext.Exception.Message, filterContext.Exception.StackTrace,
                          filterContext.Exception.InnerException == null
                              ? ""
                              : filterContext.Exception.InnerException.Message);
        Logger.Fatal(s);

        // 例外処理済みとする
        filterContext.ExceptionHandled = true;

        // エラー画面へリダイレクトする
        filterContext.Result = new RedirectResult("~/Content/Error.html");
        return;
    }

    #endregion
}

例外処理フィルタに対するテストクラスは以下の通りです。

[TestMethod]
public void TestOnException()
{
    var attribute = new ExceptionLoggerAttribute();
    Assert.IsNotNull(attribute);

    // コンテキストを生成する
    var builder = new TestControllerBuilder();
    var controller = new AuthController();

    builder.InitializeController(controller);
    var controllerContext = controller.ControllerContext;
    controller.Session[ControllerConst.UserInfoIdSessionName] = "1";

    var aec = new ExceptionContext(controllerContext, new Exception("テスト例外", null));
    aec.Result = new RedirectResult("/normarly_executed_path");

    attribute.OnException(aec);

    Assert.IsNotNull(aec);

    // リダイレクト先が変更されていることを確認する
    string s = ((RedirectResult)aec.Result).Url;
    Assert.AreEqual("~/Content/Error.html", s);
}

認証を行ったりする場合も上記にMoqなどを組み合わせることでテスト可能です。Railsの時もそうでしたが、テストに関しては便利なツールを知っているかどうかが鍵になりますね。

■参考にしたサイト Christophe Geers' Blog