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 の中身を調べる } } } }
広告