【mockito】モックのモック的な書き方

初mockitoというか初Javaの記事です。私はメイン言語がJavaのはずなのに…。プライベートではほぼ書かないせいですね…。

というわけで、お仕事中に学んだmockitoでの「モックのモック」的な書き方です。
※以下のコードは適当に書いているので、インポート文の記載もないですし実際に動かしてもいません。こういう書き方できることだけ伝えたかったのです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 適当なメソッドを持つクラス
public Class Hoge {
 
    public String getHogeStr() {
        return "hogehoge!!";
    }
}
 
// Hogeクラスをfieldに持つFugaクラス(実際には別ファイル)
public Class Fuga {
 
    private Hoge hoge; 
 
    public Hoge getHoge() {
        return this.hoge;
    }
}

的な構造のクラスがあり、それを使用するロジックがあるとします。

1
2
3
4
5
6
7
8
9
public Class Logic {
 
    private Fuga fuga;
 
    public void echoHoge() {
        Hoge hoge = fuga.getHoge();
        System.out.println(hoge.getHogeStr());
    }
}

さらにLogicクラスの対する以下のようなテストがあるとします。ここでFugaクラスやHogeクラスをモック化して扱いたいという場合のお話です。
以下のように書くと、モックのさらにモックを設定できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Class LogicTest {
 
    // モック化されたFugaクラスにインジェクションするモッククラス
    @Mock
    private Hoge hoge;
 
    // Logicクラスへインジェクションするモッククラス
    @Mock
    private Fuga fuga;
 
    // mockのinject対象のクラス
    @InjectMock
    private Logic logic;
 
    @Test
    public void test() {
        when(fuga.getHoge()).thenReturn(hoge); // モックのモックをthenReturn()に設定する
        when(hoge.getHogeStrge()).thenReturn("fugafuga!!") // モック内でさらにモック化したい処理をthenReturn()に設定する
        // 標準出力に「fugafuga!!」が表示されるはず。
        logic.echoHoge();
    }
}

ということです。これを実現するために同期と2時間ほど格闘しました…。(結果同期が解決しました。)

モックのモックとかもはや何したいか分からないという意見はあると思いますが、込み入った実装でこのような方法を使わざるを得なかったのです。(実際にはインナークラスやらメソッドチェーンやらで、恐ろしく複雑な実装箇所のテストでした…)