Mockソリューションを試す。 EasyMock と jMock の比較


ここまでで EasyMock と jMock の簡単な使い方を見てきました。
まだまだ使いこなしてはいないのですが、ここまでの知識をまとめておきたいと思います。

まず、Mock と Stub の違いについて。
EasyMock とか jMock に触れる前は、Mock と Stub が自分の中で明確に区別できていませんでした。
Wikipediaによると両者は異なるもので、Mock は Stub と比較して正しく利用されているかを検証する機能が付加されているとの事です。
確かに今まで Stub と認識していたものは、「呼ばれたときに値を返す」部分を代用する様なものでした。
しかし EasyMock や jMock はメソッドが想定されたパラメータ、順序で呼ばれるかを検証することができました。
この点で Stub とは 区別される物のようです。Mock が Stub の一種と言うことですね。

さて、 EasyMock、jMock ともに機能に大きな違いはなさそうです。
  • interface に対する Mockの作成
  • concrete class、abstract class に対する Mockの作成
  • メソッドが呼ばれているかを検査
  • メソッドが想定するパラメータで呼ばれているかを検査
  • メソッドが想定する順番で呼ばれているかを検査
  • メソッドの戻り値を偽造

また、基本的な使い方の比較をコードでしてみます。
まず、Mock を作る部分。
 //EasyMock
 mock = createMock(IService.class);

 // jMock
 context = new Mockery();
 mock = context.mock(IService.class);
次に想定される結果を検査する部分。
EasyMockの場合。
 // モックオブジェクトに対して想定される呼び出しを記述します。
 mock.echo();

 // 実際にクラスを実行してモックオブジェクトが想定通り呼び出されるかチェックします。
 replay(mock);
 sample.execute();
 verify(mock);
jMockの場合
 // モックオブジェクトに対して想定される呼び出しを記述します。
 context.checking(new Expectations() {
    {oneOf(mock).echo();
     }});

 // 実際にクラスを実行してモックオブジェクトが想定通り呼び出されるかチェックします。
 sample.execute();
 context.assertIsSatisfied();
EasyMockは想定される呼び出しを記述し、replay〜verifyメソッドで囲われた部分を検査します。
jMockは想定される呼び出しを context.checkingメソッド内のExpectationsクラス初期化子に記述し、context.checking〜context.assertIsSatisfiedメソッドで囲われた部分を検査します。
個人的には jMock の書き方の方が決められた場所が明確で好きなのですが、好みの問題かもしれません。

他にも "Mock" という文字列を含むソリューションがありましたが、試すまでには至りませんでした。
まず rMock なのですが、対応していないのかもしれないのですが TestNGにからの利用方法がわからなかったので、試しませんでした。
ただ、ドキュメントを読む限り BDD的な要素を絡めているようでおもしろそうではあります。
あと、ClassMock と呼ばれるものもありましたが、こちらは Mock と呼ばれるには必要な、正しく呼ばれているかを検証する機能がなく、簡単にクラスを作るための仕組みを提供している様です。
Mockとしての機能は他のソリューションに委ねている様で、ドキュメントにも jMock と連携した場合の例が載せられています。

Mock の使いどころとして浮かぶのは Servlet とかのテストなのではないでしょうか。
つまり擬似的な実装クラスを作るのが面倒な部分です。
Wicket だと WicketFilter クラス何かは Mock を使ったテストなんかは有効なのではと思います。


Comment