ASP.NET サーバーコントロール 単体テスト with TypeMock + MSTest

ASP.NET サーバーコントロール 単体テスト with TypeMock + MSTest

HTMLレンダリングのテストは以前からできていたのだが、
Redirect によるページ遷移の部分をどうテストするのかが課題だった。
Redirect の呼び出しを TypeMock を利用することによってテスト可能にする。

テストフレームワークは VisualStudio 2008 Professional で利用できるようになったこともあるので MSTest

(当初 Native Mock 使ってみようかと思ったが Reflective Mock で記述した。
なので TypeMock 無料版でもいけるはず。現在は入れたばかりなので Enterprise 評価モード)

テストしたいサーバーコントロール。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ServerControl1
{
    [ToolboxData("<{0}:ServerControl1 runat=\"server\" />h")]
    public class ServerControl1 : WebControl
    {
        protected override void OnPreRender(EventArgs e)
        {
            HttpContext.Current.Response.Redirect(ResolveUrl("~/tako.aspx"), true);
        }
    }
}

テストコード。テストコードの最初の枠組みは VisualStudio 2008 で、上記の OnPreRender に対して「単体テストの作成」を行う。
これにより protected メソッドに対するアクセサ(ServerControl1_Accessor)をVS2008が自動的に生成してくれる。

using ServerControl1;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Hosting;
using TypeMock;

namespace TestProject1
{
    /// <summary>
    ///ServerControl1Test のテスト クラスです。すべての
    ///ServerControl1Test 単体テストをここに含めます
    ///</summary>
    [TestClass()]
    public class ServerControl1Test
    {
        HttpContext savedContext;

        #region 追加のテスト属性
        //各テストを実行する前にコードを実行するには、TestInitialize を使用
        [TestInitialize()]
        public void MyTestInitialize()
        {
            MockManager.Init();
            savedContext = HttpContext.Current; // 一応保存しとく
        }

        // 各テストを実行した後にコードを実行するには、TestCleanup を使用
        [TestCleanup()]
        public void MyTestCleanup()
        {
            MockManager.Verify();
            HttpContext.Current = savedContext;
        }

        #endregion

        /// <summary>
        ///OnPreRender のテスト
        ///</summary>
        [TestMethod()]
        [DeploymentItem("ServerControl1.dll")]
        public void OnPreRenderTest()
        {
            Mock targetMock = MockManager.MockAll(typeof(ServerControl1.ServerControl1), Constructor.NotMocked);
            targetMock.ExpectAndReturn("ResolveUrl", "ResolveUrl succeeded").Args("~/tako.aspx"); // Pageの中にコントロールを配置していないので、そのままでは ResolveUrl が失敗する。"ResolveUrl succeeded" で差し替える。

            Mock responseMock = MockManager.MockAll(typeof(HttpResponse), Constructor.NotMocked);
            responseMock.ExpectCall("Redirect").Args("ResolveUrl succeeded", true); // Response.Redirect の第二引数なしでの呼び出しは Verify に失敗する。第一引数は上記 ResolveUrl が返した仮の値のはず

            {
                string appVirtualDir = "/Site1"; // Webアプリケーション 仮想ディレクトリ
                string appPhysicalDir = @"C:\temp\ServerControl1\Site1"; // Webアプリケーション 物理ディレクトリ
                string page = "Default.aspx"; // ページファイル
                string queryString = "a=1&b=2";
                StringBuilder sb = new StringBuilder();

                using (StringWriter sw = new StringWriter(sb))
                {
                    HttpWorkerRequest wr =
                        new SimpleWorkerRequest(appVirtualDir, appPhysicalDir, page, queryString, sw);

                    HttpContext.Current = new HttpContext(wr);

                    ServerControl1_Accessor target = new ServerControl1_Accessor();

                    EventArgs e = new EventArgs();
                    target.OnPreRender(e);
                }
                // レンダリング結果が必要なら sb の中身を調べる
            }
        }
    }
}
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。