それではさっそく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が想定される引数で呼び出されていることを確認している。