それではさっそくMockitoを使ったテストケースを書いてみよう。
MockitoのダウンロードページではZIPアーカイブのディストリビューションと、ライブラリのJARファイルが単体で配布されている。使用するだけであればJARファイルをダウンロードするといいだろう。クラスパスに追加すれば準備完了だ。本稿では最新のRCである1.8.0-RC2を使用した。
まず、以下のようなインタフェースを持つDAO(Database Access Object)があるとする。
public interface ItemDao {
public Item findItem(int id) throws IllegalArgumentException;
}
public class Item {
public int itemId;
public String itemName;
public int price;
public Item(int itemId, String itemName, int price){
this.itemId = itemId;
this.itemName = itemName;
this.price = price;
}
}
テスト対象はこのDAOを使って商品の価格を計算する以下のクラスだ。DAOの実装はDIコンテナなどを使用して設定することを想定している。
public class Calculator {
protected ItemDao itemDao;
public int calculate(int itemId){
Item item = itemDao.findItem(itemId);
// 消費税を計算
int total = (int) Math.floor(item.price * 1.05);
// 税込価格が10,000円以下の場合は送料500円が必要
if(total < 10000){
total = total + 500;
}
return total;
}
}
最も簡単なテストケースは以下のようになる。
import static org.mockito.Mockito.*; // ... (1)
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculatorTest {
@Test
public void testCalculatePrice() {
Calculator calculator = new Calculator();
// DAOのモックオブジェクトを作成 ... (2)
ItemDao mock = mock(ItemDao.class);
calculator.itemDao = mock;
// findItem()の引数が1の場合の戻り値を設定 ... (3)
when(mock.findItem(1))
.thenReturn(new Item(1, "Eclipseプラグイン開発徹底攻略", 3900));
int result = calculator.calculate(1);
// DAOが引数=1で呼び出されていることを確認 ... (4)
verify(mock).findItem(1);
// 戻り値の確認
assertEquals(4595, result);
}
}
まず注意してほしいのが、(1)でorg.mockito.Mockitoのstaticメンバをインポートしていることだ。Mockitoではstaticインポートとメソッドチェーンを活用してモックオブジェクトの振る舞いや検証をDSL的に記述することができる。IDE側でMockitoクラスのstaticメンバが自動的にstaticインポートされるよう設定しておくといいだろう。
続いて(2)ではMockito#mock()メソッドでモックオブジェクトを作成している。ここではDAOのインタフェースを指定してモックオブジェクトを作成しているが、実装クラスを指定し、特定のメソッドの挙動のみモックで差し替えることも可能だ。
(3)ではDAOのfindItem()メソッドが呼び出された時の戻り値を設定している(設定しない場合はnullが返却される)。ここでは引数が1で呼び出された場合の戻り値のみを設定している。なお、thenReturn()の代わりにthenThrow()を用いることで戻り値を戻すのではなく、例外をスローすることも可能だ。
when(mock.findItem(0))
.thenThrow(new IllegalArgumentException());
(4)ではDAOが想定される引数で呼び出されていることを確認している。