JMockitを使用した単体テスト5
一部分だけモックにする
オブジェクトのうち、いくつかのメソッドのみモックにし、それ以外は実際の処理を行いたい場合、
- Static partial mocking
- Dynamic partial mocking
の2通りの方法があります。
以下のテスト対象クラスのテストクラスを作成してみます。
テスト対象
public class Dice { public int play1() { return new Random(System.currentTimeMillis()).nextInt(6) + 1; } // テスト対象のメソッド public int play2(final int n) { int max = 0; for (int i = 0; i < n; i++) { int value = play1(); // (a) ここでモックを使う max = Math.max(max, value); } return max; } }
play2はplay1を実行するので、試験を行う場合は、play1はモック、play2は実際の処理でなければなりません。今までの方法だと、Diceをモックにすると双方モックになってしまって試験できません。
Static partial mocking
Static partial mockingのテストクラスは以下の通りです。
テストクラス
@Test public void testPlay2_Static() { final int n = 3; new Expectations() { // (1) Dice#play1のみモックとし、それ以外のメソッドは実処理を行う @Mocked(methods = {"play1"}) Dice dice; { dice.play1(); // (2) play1が呼ばれる毎に順番に値を返す returns(3, 5, 2); } }; final Dice dice = new Dice(); int result = dice.play2(n); assertEquals(5, result); }
(1)のように@Mockedのmethodパラメータのモックにするメソッド名を文字列で指定します。メソッドの指定にはいくつかのルールがあります。
Dynamic partial mocking
Static dynamic mockingでは、モックにするメソッドを文字列で指定するため、メソッド名を変更した場合にIDEのリファクタリングで自動的に変更されません。この問題を解決するのがDynamic partial mockingです。
テストクラスは以下の通りです。
テストクラス
@Test public void testPlay2_Dynamic() { final Dice dice = new Dice(); final int n = 5; // モックにするオブジェクトを指定する。複数指定も可。 new Expectations(dice) { { dice.play1(); returns(3, 2, 1, 5, 2); } }; int result = dice.play2(n); assertEquals(5, result); }
上記のように、new Expectations()の引数にモックにするオブジェクトかクラスを指定すると、そのブロック内で呼ばれてるメソッドのみがモックになります。