EasyMock
http://www.easymock.org/index.html
インターフェイスを与えることで簡単にモックテストを行えるように作られたモック。
wildcatsさんの蝋人形の館(2004/3/17)から引用
EasyMockにパッチを当て、インターフェイスを実装していないクラスのメソッドにMockを当ててテストしてみた。
久しぶりで忘れていたことが多数あったので 手順をメモしておく。
- easymock-1.0.jarをダウンロードする。
- easymock-patch-1.0をダウンロードする。
- 1)・2)のJARを解凍して2)を1)にかぶせて再度jarを作る。
- bcel5.1とCGLib1.0rc2をダウンロードする。
- サンプルをテストする。
注意点
- CGLib1.0 Releaseではこのパッチは動作しない。
- easymock1.01bではこのパッチは動作しない。
引用ここまで
以下の文章は、JAVA PRESS VOL.34(技術評論社)に掲載していただいた記事から、EasyMockについて記述した部分を抜き出したものです。
●自作クラスのモックテスト(EasyMock)
モックは何もJ2SEのクラスだけに限って必要になるわけではありません。
今度は(Wiki掲載時の注:元記事では、この前にMockObjectsを利用したDAOのテスト方法についての記述がある)MemberInfoDAOを使用するビジネスロジックの開発を考えて見ましょう。同様にテストを作って見ます。
ビジネスロジックを実装したクラスMemberには、指定されたメッセージを指定された範囲の年齢の会員にメールするdistributeMessageByAge(String message, int low, int high)というメソッドを持つと想定してみましょう。
テストプログラムは次のようになります。
public class MemberTest extends TestCase { public void testDistributeMessageByAge() throws Exception { Member m = new Member(); // MemberにMemberInfoDAOを設定 m.testDistributeMessageByAge("hello\nThis is test message.\nBye", 10, 15); // 検証 } }
ここで必要なのは、10と15の2つの引数でsearchの呼び出しが可能なMemberInfoDAOのモックです。もちろん、現時点ではMemberInfoDAOにはsearchメソッドしか実装されていないため、モックは無名クラスをその場で作成すれば済むでしょう。しかしメソッドが複数ある場合はどうでしょうか? それにMemberInfoDAOはデフォルトコンストラクタでJNDIのルックアップを行うクラスですから無名クラスを作るといってもJNDIの設定が必要となってしまいます。
EasyMockはインターフェイスを与えるとメソッドの引数と呼び出し順、返送値、スローする例外などを設定可能なモックを生成するツールです。
EasyMockのインストール
EasyMockはhttp://www.easymock.org/Downloads.htmlからダウンロードします。2003年11月の最新版は1.0.1bです。なおライセンスはMITライセンスとなっています。
ダウンロードしたzipを適当なディレクトリに展開するとeasymockバージョン番号ディレクトリが作成されその下にjavadocなどが展開されます。実行時に必要なのはディレクトリ直下のeasymock.jarだけです。
EasyMockは名前の通り、簡単にモックを生成/利用するためのツールです。主な制限事項としてはインターフェイスからしかモックを作成できないことが挙げられますが通常のテストには十分な機能が提供されます。
EasyMockを利用すると
- テストターゲットが呼び出すメソッドと引数の登録
- 呼び出しの返送値と連続して呼び出される回数の設定
- 呼び出しの結果スローする例外の設定
が可能となります。
先程のリストを例にして、Member#testDistributeMessageByAgeの呼び出しによってMemberがMemberInfoDAOを1回呼び出して結果を取得するという処理を記述してみましょう。なお、MemberInfoはMemberInfoDAOが実装しているインターフェイスと想定してください(サンプルはsrc2ディレクトリに格納してあります。ant junit2によって実行されます。なお、サンプルのMemberは単に呼び出しの結果を標準出力に表示するだけの実装です)
public class MemberTest extends TestCase { public void testDistributeMessageByAge() throws Exception { Member m = new Member(); // インターフェイスを与えてモックコントローラを作成 MockControl c = new MockControl.createControl(MemberInfo.class); // モックのインスタンスをコントローラから取得 MemberInfo mock = (MemberInfO)c.getMock(); // 呼ばれるメソッドと期待する引数(ここでは10と15)をモックに設定 mock.search(10, 15); // 返送値を作成 ArrayList list = new ArrayList(); list.add("0000001"); list.add("0000002"); // 返送値をコントローラに設定) c.setReturnValue(list, 1); // 設定状態から呼び出し可能状態に変更します。 c.replay(); // MemberにMemberInfoDAOを設定 m.setDAO(mock); m.testDistributeMessageByAge("hello\nThis is test message.\nBye", 10, 15); // 設定した呼び出しが行われたか検証 c.verify(); // 呼び出し可能状態から設定状態に戻す c.reset(); mock.search(20, 25); // 呼び出しの結果スローする例外を設定 c.setThrowable(new NotFoundException("test"), 1); ... } }
このように、EasyMockでは、コントローラとモックの2つのオブジェクトを使用してモックの動作を設定します。リストを見ての通り、EasyMockを利用すると簡潔にモックを記述することができます。是非とも、みなさんのテストに役立ててください。
Keyword(s):
References: