ASP.NET というか IIS を使ってアプリケーション開発を行っている場合、一度はお世話になっていると思う URL Rewrite ですが、割と書き方が難しいです。
IIS Manager にパターンのテストツールはありますが、大した機能は持ってません。
パターンをテストした後は、実際にアクセスして確かめるという手順を踏む場合が多いと思いますが、IIS 以外には自動で行うためのツールも用意されているみたいでした。
mod_rewrite 向けにはあるのに、IIS の URL Rewrite 向けにはないことにショックを受けたので、土日を利用して同じような機能を持つライブラリを書きました。
仕組みとしては IIS Express を裏側で立ち上げて、リクエストを投げているだけです。IIS Express はフルの IIS と同じ機能が使える上、コマンドラインから単体実行が簡単に行えるので便利です。
Running IIS Express from the Command Line | Microsoft Docs
http://www.reimers.dk/jacob-reimers-blog/testing-your-web-application-with-iis-express-and-unit-tests
テストフレームワークには xUnit を使いました。今のところ他に対応させる気はあまりないです。
使い方は NuGet でパッケージをインストールするだけで大体は整う感じです。簡単ですね。
当然ながら IIS Express のインストールは必要ですが、Visual Studio をインストールしていれば、同時に IIS Express も入っているはずです。
Install-Package xunit Install-Package xunit.runner.visualstudio Install-Package IisExpressTestKit
パッケージ名は変えるかもしれませんが、今はこんな名前になっています。
インストールが完了したら Rewrite.config というファイル名で URL Rewrite の定義を用意します。ファイル名が固定なのは止めたいですが、xUnit の IClassFeature と上手く同居させる方法が浮かびませんでした。
<?xml version="1.0" encoding="utf-8"?> <rules> <rule name="Rewrite" stopProcessing="true"> <match url=".*" /> <action type="Rewrite" url="/translated/{R:0}" /> </rule> </rules>
作成した Rewrite.config は出力ディレクトリにコピーする設定にしておきます。この辺りもファイル名が固定の弊害なので、将来的には何とかしたい部分ではあります。
準備は出来たので、あとはテストケースを作成します。IisRewriteTestBase クラスを継承して、コンストラクタを作成すればあとは自由にテストを書くことが出来ます。
実際に Inbound の Rewrite ルールに対するテストを書いてみると、以下のような感じになります。
public class UrlRewriteTest : IisRewriteTestBase { public UrlRewriteTest(IisExpressFixture fixture) : base(fixture) { } [Fact] public void Rewriteルールのテスト() { Iis.Request("/hoge") .IsPath("/translated/hoge") .IsStatusCode(HttpStatusCode.OK); Iis.Request("/foo/bar/baz") .IsPath("/translated/foo/bar/baz") .IsStatusCode(HttpStatusCode.OK); } }
流れとしては、指定したパスにリクエストを投げて、書き換えられたパスとステータスコードを確認という感じです。メソッドチェインで比較的わかりやすく書けている気がしています。
このテストを実行すると、裏側で IIS Express が立ち上がってテストケースに書いたとおりにリクエストを投げて、その処理結果を確認していきます。
Rewrite.config に書いた通り、URL Rewrite によってパスが書き換えられるのを、テストすることが出来ました。今のところは Inbound の一部のみ書けるようになってます。
時間があれば IsDirectory や IsFile への対応や、Outbound への対応も行いたいです。