特集:ASP.NET MVC Contribのテスト支援機能(後編)
URLパターンを用いてテストを行う
URLルーティングの設定を変更しながら、ASP.NET MVCアプリのテストを追加していく方法について説明。また、MvcContribのテスト支援機能以外の機能についても簡単に紹介する。
MVC Contribは、ASP.NET MVCを便利に使うためのオープンソース・ライブラリだ。前編では、MVC Contribを活用してテストを簡単に行う方法について紹介した。後編となる本稿では、URLルーティングの設定を変更しながら、テストを追加していく方法について解説する。コードはC#で記述する。
新しいURLルーティングとテストを追加
それでは、新しいURLパターンを追加していこう。ここでは、前編で紹介した「/article/100/page/2(100個目の記事の2ページ目)」というURLをテストするとしよう。このURLであれば、ArticleControllerのIndexメソッドが呼び出され、第1引数に「100」が、第2引数に「2」が渡されることを想定している。
コントローラーの記述
まず、最初に呼び出されるコントローラーを以下のように記述する。Indexメソッドでは、記事ID「aid」とページ・ナンバー「pagenum」を引数として受け取る。
using System.Web.Mvc;
public class ArticleController : Controller
{
public ActionResult Index(int aid, int pagenum)
{
// 本来はaidやpagenumを使って処理を行う
return View();
}
}
|
テストの記述
次に、テストを記述する。ここでは、前回作成した「RouteConfigTest」というテスト・クラスの中に、「/article/100/page/2」というURLのテストを記述する(次のコードを参照)。
[TestMethod]
public void 記事ページが正しく呼び出されるはず()
{
"~/article/100/page/2".Route().ShouldMapTo<ArticleController>(action => action.Index(100, 2));
}
|
前回のテストと同様にShouldMapToメソッドを呼び出してテストを行っている。ここでは、アクションメソッドに「Index(100, 2))」という引数を指定している点に注目してほしい。第1引数のaidに「100」が、第2引数のpagenumに「2」がセットされることを想定している。
このようにMVC Contrib TestHelperでは、ラムダ式でテストを記述できるため、コントローラーのシグネチャが変わったときにコンパイル・エラーで気付けるメリットがある。
テストがエラーとなることを確認
それでは、テストを実行してみよう(次の画面はその実行結果)。まだURLルーティングを設定していないため、テストはエラーになるはずである。
追加したテストがエラーになることを確認できた。ルーティングを追加するときは、既存のテストが全部パスしていて、追記したテストだけがエラーになっていることを確認しておくとよいだろう。
ルーティングの設定を追加
それでは、記事用のURLルーティング設定を(次のコードのように)追加してみよう。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// 新しいルート設定を追加(今回のテスト対象)
routes.MapRoute(
name: "Article",
url: "article/{aid}/page/{pagenum}",
defaults: new { controller = "Article", action = "Index" }
);
// 既定ルート
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
|
URLルーティングを設定するには、MapRouteメソッドを用いてURLのパターン文字列を指定する。優先度が高いルートを先に指定する必要があるため、Defaultルートの前に新しいArticleルートを追加している。
URL設定ではマッチングさせるパターン文字列を記述する。完全一致だけではなく「{中かっこ}」を用いた部分一致を記述できる。ここでは「article/{aid}/page/{pagenum}」と書くことで、記事IDとページ番号をパラメーターとして受け取るようにしている。
なお、URLルーティングの設定方法については、この記事を参考にするとよいだろう
テストが成功することを確認
再びテストを実行してみよう。今度は(次の画面のように)全てのテストが成功するはずである。
このような手順でテストを実施することで、既存のルーティング設定を壊すことなく、新しいルーティングを追加できる。
HTTPメソッドのテスト
続けて、別のパターンのテストについても見ていこう。開発をしていると、GETやPOSTといった特定のHTTPメソッドのルーティングを制御したいケースもあるだろう。この場合のテストの書き方について紹介する。
ここでは、記事をPOSTでアップロードする「article/{aid}/upload」いうURLを追加してみる。
コントローラーの記述
まず、呼び出されるコントローラーを記述する。呼び出されるUploadメソッドでは、引数として記事ID「aid」とファイル「uploadFile」を受け取る。
public class ArticleController : Controller
{
……省略……
// リクエストがHTTP POSTのときのみ呼び出される属性
[HttpPost]
public ActionResult Upload(int aid, HttpPostedFileBase uploadFile)
{
// 本来はaidやuploadFileを使って処理を行う
return View();
}
}
|
HTTPメソッドに応じたテスト
次に「/article/100/upload」というURLのテストを記述する
[TestMethod]
public void 記事アップロードが正しく呼び出されるはず()
{
"~/article/100/upload".WithMethod(System.Web.Mvc.HttpVerbs.Post)
.ShouldMapTo<ArticleController>(action => action.Upload(100, null));
}
|
ここでのポイントはRouteメソッドの代わりにWithMethodメソッドを使っていることである。WithMethodメソッドの戻り値はRouteメソッドと同じくRouteDataクラスである。そのため、ShouldMapToメソッドを呼び出して、アクションのテストを行うことができる。WithMethodメソッドの引数にPostを渡すことでテスト対象のリクエストがPOSTメソッドであることを示している。
ルーティングの設定を追加
最後に、URLルーティングの設定を追加する。POSTだけルーティングするには、constraintsパラメーターにて「httpMethod」を設定する。
public static void RegisterRoutes(RouteCollection routes)
{
……省略……
// 記事ページにアップロード(POSTのみ対象)
routes.MapRoute(
name: "Article Uplopad",
url: "article/{aid}/upload",
defaults: new { controller = "Article", action = "Upload" },
constraints: new { httpMethod = new HttpMethodConstraint("POST") }
);
……省略……
}
|
テストの実行
この状態でテストを実行するとテストが成功する。MVC Contrib TestHelperを使うことで、ブラウザを使用せずにさまざまなテストが可能になることが分かったと思う。
MVC Contrib TestHelperが提供するFakeクラスについて
なお、本稿ではルーティングのテスト方法について紹介したが、TestHelperには、テストに役立つFakeクラスも含まれている。Fakeクラスとは例えば、セッション情報やログイン状態を偽装するクラスなどである。
主要なFakeクラス(FakeHttpContext、FakeHttpRequest、FakeHttpResponse、FakeHttpSessionState、FakeIdentity、FakePrincipal)とBuilderクラス(TestControllerBuilder)のクラス図を以下に記載しておくので、必要があれば利用してみるとよいだろう。
ほかのMVC Contribの機能について
今回は、MVC Contribのテスト支援機能について紹介した。Codeplexのサイトによれば、MVC Contribではテスト支援機能以外にも多くの機能が提供されている。
Contrib区分 | 機能・部品 |
---|---|
Portable Areas | 複数のプロジェクトで使用できるポータブルなエリア(区分) |
UI Helpers | GridコントロールなどのUI部品 |
Model Binders | Derived Type Model Binder、Castle Binder(Castleプロジェクト連携)などのモデル・バインダー |
Controller Factories | Spring.Net、Unity、Castle Windsor、StructureMapといったDIコンテナ連携 |
Controllers | AcceptPostAttribute、強い型のRedirectToAction、Fluent Controllerなど |
Filters | PostOnly Filter、PreCondition Filter、Layout Filterなどのフィルタ |
View Engines | Brail、NDjango、NHaml、NVelocity、SharpTiles、Spark、StringTemplate、XSLTなどのビュー・エンジン |
Unit Testing Library | ユニット・テストのためのライブラリ |
Utilities | ユーティリティ機能 |
T4MVC | T4テンプレートを用いたユーティリティ |
Channel9で動画も公開されているので、気になるライブラリがあれば、活用を検討してみてはいかがだろうか。
1. ASP.NET MVCアプリのURLのテストを簡単に行う
ASP.NET MVCを便利に使うためのオープンソース・ライブラリ「MvcContrib」のテスト支援機能を活用して、ASP.NET MVCアプリのURLをテストする方法を説明する。