【コラム】
前回に引き続き、ユニットテストに利用するためのモックオブジェクトを簡単に作成することができる「EasyMock」について紹介する。
EasyMockの最も基本的な使い方は、対象のメソッドを特定の引数を与えて実行した場合に、正しい戻り値を返すようなモックを作成するというものである。しかしそれだけではなく、メソッドに渡された引数が想定通りであるかどうかをチェックするというような使い方もできる。例えば前回のサンプルとして作成したDataSourceクラスのモックは、get()メソッドが"testkey"という引数を受け取るように想定したものである。したがって、次のような"testkey"以外の引数を渡す呼び出しはエラーになる()
String result = sample.findValue("wrongkey");
想定する引数は、もう少し柔軟性を持たせることもできるようになっている。例えば"testkey"限定ではなく、任意の文字列を渡せるようにしたい場合には、EasyMockクラスのanyObject()メソッドを利用して次のようにモックの振る舞いを定義すればよい。anyObject()は任意のオブジェクトを表すメソッドなので、Stringにキャストして使用している。
EasyMock.expect(mock.get((String)EasyMock.anyObject())).andReturn("resultValue");
EasyMockクラスには、anyObject()以外にも引数の型をチェックするために様々なメソッドが用意されている。主なものを以下に挙げる。
この他に、正規表現を使って受け取る文字列を指定できるmatches()やfind()といったメソッドもある。対象が文字列であるならば、これらのメソッドを使えばより柔軟な引数チェックを行うことが可能だ。
EasyMockでは、作成したモックに対するメソッド呼び出しについて、その呼び出し回数や呼び出し順序が適切かどうかを検証する機能も備えられている。この検証はEasyMockクラスのverify()メソッドを呼び出すことで実行できる。例えば次のコードでは、DataSourceのモックとしてget()メソッドの呼び出しに対する振る舞いを定義している。この場合、デフォルトではget()は1回だけ呼び出されることを想定したものとなる。したがって、get()が呼ばれていなかったり、2回以上呼ばれていたりすると、のような感じでテストは失敗する。
呼び出し回数を複数回にしたり、メソッドの呼び出し順序を検証することもできる。これを試すために、DataSourceインタフェースを書き換えて、次のように3つのメソッドを持つようにしてみた。
public interface DataSource {
public String get(String key);
public void openSource();
public void closeSource();
}
ここで、get()を呼ぶ場合には必ず最初にopenSource()メソッドを、最後にcloseSource()メソッドを呼ばなければならないことが決められていると仮定する。そのような呼び出しを行うメソッドとして、EasyMockSampleクラスに次のようなgetValues()メソッドを追加した。このメソッドは、指定された回数だけget()を実行してデータを取得し、その結果を返すというものである。
public List<String> getValues(int number) {
List<String> values = new ArrayList<String>();
this.dataSource.openSource();
for(int i=0; i<number; i++) {
this.dataSource.get("testkey");
}
this.dataSource.closeSource();
return values;
}
このgetValues()メソッドが、正しい順序でDataSourceのメソッド呼び出しを行っていることを検証するには、次のようなテストを実行すればよい。
@Test
public void testFindValue() {
// 動作モードを指定してモックを作成
DataSource mock = EasyMock.createStrictMock(DataSource.class);
// モックの振る舞いを記録
mock.openSource();
EasyMock.expectLastCall().times(1);
EasyMock.expect(mock.get((String)EasyMock.anyObject())).andReturn("resultValue");
EasyMock.expectLastCall().atLeastOnce();
mock.closeSource();
EasyMock.expectLastCall().times(1);
EasyMock.replay(mock);
// テストを実行
EasyMockSample sample = new EasyMockSample();
sample.setDataSource(mock);
List<String> result = sample.getValues(3);
// メソッド呼び出しを検証
EasyMock.verify(mock);
}
まず、モックの作成にはEasyMock.createStrictMock()メソッドを使う。EasyMockクラスでは、verify()メソッドによるチェックの厳密さを決める3つのモードが用意されている。これは、次のようにモック作成時に使うメソッドによって決定される。
EasyMock.exceptLastCall().times()メソッドは、直前のメソッド呼び出しの回数を指定するメソッドである。この例ではopenSource()とcloseSource()の後でtimes(1)を設定しているので、それぞれ1回の呼び出しを想定していることになる。したがってこれらのメソッドが呼ばれなかったり、2回以上呼ばれたりした場合にはテストは失敗する。times(1, 5)のようにした場合には、1回以上5回以下の呼び出しを想定するという意味になる。
EasyMock.exceptLastCall().atLeastOnce()メソッドは、直前のメソッド呼び出しが必ず1回以上行われることを指定するものである。この例の場合には、get()メソッドが1回以上呼ばれることを想定していることになり、1回も呼ばれなかった場合にはテストは失敗する。
実際のテストとしてはgetValues(3)を実行しているので、getValue()が正しく動作するのであれば、まずopenSource()が呼ばれ、続いてget()が3回呼ばれて、最後にcloseSouce()が呼ばれる。これはモックに設定した振る舞い通りの呼び出し順序になっているので、verify()によるチェックは成功するはずである。
もしここで、getValue()内にopenSource()やcloseSource()を忘れるなどのバグがある場合には、verify()によるチェックが通らず、のようなエラーになる。
このように、EasyMockではモックの振る舞いに関して様々な検証事項を設定することができるようになっており、様々なテストに適用することが可能である。効果的に利用すれば、テストのための工程を大幅に削減しすることができるだろう。
| 理研、脳・脊髄形成に必要な神経板湾曲の仕組みを解明 [20:16 5/25] |
| 京大、「慢性閉塞性肺疾患」患者の労作時呼吸困難は鍼治療が有効と実証 [20:08 5/25] |
| 120Hz SHVカメラ用イメージセンサーを使った撮像装置 - SHVフルスペック化へ [18:10 5/25] |
| 京大、視覚による物体認知は前頭前野からのトップダウン信号が重要と確認 [17:45 5/25] |
| 製品数の拡大だけでなくBCPの展開なども含めた総合力で事業の強化を図るTI [17:25 5/25] |
|
【インタビュー】真木よう子 - 年齢ごとに等身大の女優になりたい [21:30 5/27] エンタメ |
|
[リアル・スティール]DVDとBDセットがオリコンとTSUTAYAで初登場首位 特別映像も公開 [21:11 5/27] エンタメ |
|
【連載】これだけは要チェック! TOEIC(R)単語帳 第108回 今回のお題は…「issue」 [20:00 5/27] キャリア |
|
TVアニメ『ペルソナ4』、新規カットを加えた再編集版を劇場でイベント上映 [20:00 5/27] ホビー |
|
「ギャラクシーエンジェル」の大月悠祐子がWEBで新連載 [19:52 5/27] ホビー |
4つの診断で、自分の適性を見つめなおそう!
働くこと・挑戦し続けることへの思いを綴ったインタビュー
あなたにピッタリのアドバイスを読むことができます。
転職に必要な情報が収集できます
企業からアプローチのメッセージが届きます。