2014年11月26日水曜日

移行サンプル:Telerik JustMock によるモック化① final メソッドのモック化 - from "Prig: Open Source Alternative to Microsoft Fakes" Wiki -

まとまってきたドキュメントを日本語の記事にもしておくよシリーズ第 5 段!(元ネタ:Prigwiki より、MIGRATION: Final Mocking by Telerik JustMock。同シリーズの他記事:1 2 3 4

やっと折り返し地点ですね。今回からは 3 回に渡る JustMock の公式ドキュメントにあるサンプルを実装するシリーズとなります。まずは、「Final Mocking samples」を Prig に移行してみましょう。


以下の記事、ライブラリを使用/参考にさせていただいています。この場を借りてお礼申し上げます m(_ _)m
Using Jekyll with Pages - GitHub Help
Can I share a Microsoft Fakes unit test with a developer using Visual Studio Professional - Stack Overflow
shim a sealed class singleton method and with MS Fakes - Stack Overflow
Search - GitHub Anonymously Hosted DynamicMethods Assembly
API Hooking with MS Detours - CodeProject
Incorrect solution build ordering when using MSBuild.exe - The Visual Studio Blog - Site Home - MSDN Blogs
visual studio 2010 - How do I target a specific .NET project within a Solution using MSBuild from VS2010 - Stack Overflow
Advanced Usage | JustMock Documentation
.net - Is there any free mocking framework that can mock static methods and sealed classes - Stack Overflow
Modern ASP.NET Webskills by @calebjenkins





目次

準備
このサンプルでは、シリーズということもあり、1 つのソリューションに複数のプロジェクトを追加するという構成を採っています。





なお、この例は、間接的に呼び出される対象が、GAC に登録されていない Assembly に含まれており、以前の例(MolesFakes)とは異なることに注意してくださいね。

これまでは Package Manager Console で間接スタブを作成する手順を実施しても問題ありませんでしたが、今後は、PowerShell(コンソール)を使えるようになることを推奨します。Package Manager Console は、仕様上、ネストしたプロンプトをサポートしていません。従って、1 度間接対象の解析を行うために Assembly を読み込むと、2 度とその Assembly を解放できないという問題があるのです。そもそも、いつも使う機能である、オートコンプリート、コマンド履歴なども PowerShell(コンソール)のものより機能的に劣ります。間接設定の追加やテストの実行時は Package Manager Console を使い、Assembly の解析時は PowerShell(コンソール)を使うということが、効率が良いでしょう。

※注※:以下の解説で、PM> で始まるコマンドは Package Manager Console で実行しますが、PS> で始まるコマンドは PowerShell(コンソール)で実行することに注意してください。

FinalMockingMigration をビルド後、出力ディレクトリを開き、以下のコマンドを実行します。プロジェクトがいくつもありますので、対象のテストプロジェクトを Default project: として選択することをお忘れなく:

ちなみに、padd -af は、Add-PrigAssembly -AssemblyFrom のエイリアスです。GAC に登録されていない Assembly の間接スタブ設定を追加する場合、コマンドの引数にフルパスを引き渡す必要があることに注意してください。PowerShell(スクリプト言語)では、コマンド (dir <target file>).FullName でフルファイルパスを取得することができます。FinalMockingMigrationTest に FinalMockingMigration.v4.0.30319.v1.0.0.0.prig が追加されれば成功です。

さて、次は、FinalMockingMigration の出力ディレクトリ上で PowerShell(コンソール)を実行し、Assembly を解析しましょう。Windows 8 を使っているのであれば、エクスプローラで対象のディレクトリを表示中、Alt、F、R のキーコンビネーションが便利ですよね。現在の位置を確認したら、ネストしたプロンプトを開始します:

Package Manager Console で利用が可能になっている種々のコマンド(Find-IndirectionTarget や Get-IndirectionStubSetting など)は、Prig をインストール後、モジュール $(SolutionDir)\packages\Prig.\tools\Urasandesu.Prig に配置されます。なので、それを PowerShell(コンソール)にインポートします:

GAC に登録していない Assembly を読み込みたい場合、System.Reflection.Assembly.LoadFrom(string) にフルパスを引き渡す必要があります。取得には・・・って、ちょっと前にやりましたね (^^ゞ:

Assembly を読み込み後、変数に設定します。ところで、履歴から実行したコマンドを呼び出し、ちょっと変更して再実行するという流れは PowerShell(コンソール)の真骨頂だと思います。Package Manager Console で同じことをしようものなら、重複した履歴を延々と遡る必要があったり、オートコンプリートによる意図しない消去を食らったりすることになるでしょう。ストレスがマッハになること請け合いです (-_-;):

GetTypes で型を確認すると、上から 3 つが対象ということがわかります。それらに対し、前のサンプルと同様のフィルタを掛けてみましょう:

結果が良さそうであれば、間接スタブ設定に変換し、クリップボードにコピーします。なお、解析が終わった Assembly を解放したい場合は、ネストしたプロンプトを終了すれば OK です。

Visual Studio に戻り、FinalMockingMigration.v4.0.30319.v1.0.0.0.prig に間接スタブ設定を貼り付けます。ビルドは通りましたか?それでは、ちょっと長くなりましたが、実際の移行を行っていきましょう!





Assert Final Method Setup
Fakes のサンプルでも言いましたが、Prig は Mock Object としての機能を持っていませんので、Moq のような別のモックフレームワークと一緒に使うことを推奨しています。しかし、どうも JustMock のサンプルは、単に Test Stub としての振る舞いが紹介されているだけのものが大半ですので、Prig のサンプルもそれと一貫性を持たせるようにしました:

はじめに、final メソッドの戻り値を入れ替えてみましょう:

fooProxy.EchoInt32().Body = (@this, arg1) => 10; で、Prig は、その final メソッドを、定数 10 を返す処理に入れ替えています。大丈夫ですよね。次、行ってみましょう!





Assert Property Get
final プロパティを入れ替えるサンプルです:

fooProxy.FooPropGet().Body = @this => "bar"; で、Prig は、その final プロパティを、定数 bar を返す処理に入れ替えています。どんどん行きますよ (^O^)





Assert Property Set
final プロパティのセッターを検証するサンプルです。これは Moq を使ったほうが簡単そうですね:

Telerik.JustMock.Behavior.Strict は、Moq.MockBehavior.Strict にあたります。従って、Setup で指定した条件を満たさない引数で対象のメンバーを呼び出した場合、MockException をスローするようになります。





Assert Method Overloads
各 final メソッドのオーバーロードを入れ替えてみましょう。間接スタブ設定を正しく追加していれば、特に迷うことは無いはずです:

特に問題は無いですよね?次に進みましょう。





Assert Method Callbacks
イベントとしてのコールバックを置換することを説明する例です。Moles の例で紹介しましたが、実装には若干のテクニックが必要です:

実装は以下の流れになります:
  1. fooProxy.AddOnEchoCallbackEchoEventHandler().Body = (@this, value) => handler += value; のように、入れ替えたいイベントの += 演算子を乗っ取り、渡されたハンドラ(value)をテストのためのデリゲート(handler)に紐付ける。
  2. 元のイベントを発行したいタイミングで、手順 1 で紐づけたデリゲート(handler)を代わりに実行する。
これで、元のイベントを発火することと同じ効果を得ることができるようになります。





Assert Generic Types and Methods
ジェネリックな型とメソッドを入れ替える例です:

ね、簡単でしょう?これに関しては、以前の記事で解説したジェネリックのサポートも、合わせてご覧いただければと思います。



0 件のコメント:

コメントを投稿