1. 概要

単体テストの課題の1つは、プライベートメソッドをモックすることです。

このチュートリアルでは、JUnitとTestNGでサポートされているPowerMockライブラリを使用してこれを実現する方法について学習します。

PowerMockは、EasyMockやMockitoなどのモックフレームワークと統合され、プライベートメソッド、finalクラス、finalメソッドのモックなどの機能を追加することを目的としています

これは、バイトコード操作と完全に別個のクラスローダーに依存することによって行われます。

2. Mavenの依存関係

まず、PowerMockをMockitoおよびJUnitとともに使用するために必要な依存関係をpom.xmlに追加しましょう。

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>1.7.3</version>
    <scope>test</scope>
</dependency>

最新バージョンはこちらこちらで確認できます。

3. 例

の例から始めましょう LuckyNumberGenerator。 このクラスには、ラッキーナンバーを生成するための単一のパブリックメソッドがあります。

public int getLuckyNumber(String name) {
    saveIntoDatabase(name);
    if (name == null) {
        return getDefaultLuckyNumber();
    }
    return getComputedLuckyNumber(name.length());
}

4. プライベートメソッドのモッキングのバリエーション

メソッドの徹底的な単体テストでは、プライベートメソッドをモックする必要があります。

4.1. 引数はないが戻り値があるメソッド

簡単な例として、引数のないプライベートメソッドの動作をモックして、目的の値を返すように強制しましょう。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

when(mock, "getDefaultLuckyNumber").thenReturn(300);

この場合、プライベートメソッド getDefaultLuckyNumber をモックして、値300を返すようにします。

4.2. 引数と戻り値を持つメソッド

次に、引数を使用してプライベートメソッドの動作をモックし、目的の値を返すように強制します。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

doReturn(1).when(mock, "getComputedLuckyNumber", ArgumentMatchers.anyInt());

この場合、プライベートメソッドをモックして、1を返すようにします。

入力引数は気にせず、ワイルドカードとして ArgumentMatchers.anyInt()を使用することに注意してください。

4.3. メソッドの呼び出しの検証

最後の戦略は、PowerMockを使用してプライベートメソッドの呼び出しを検証することです。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
int result = mock.getLuckyNumber("Tyranosorous");

verifyPrivate(mock).invoke("saveIntoDatabase", ArgumentMatchers.anyString());

5. 注意の言葉

最後に、プライベートメソッドはPowerMockを使用してテストできますが、この手法を使用するときは特に注意する必要があります。

テストの目的がクラスの動作を検証することであることを考えると、単体テスト中にクラスの内部動作を変更することは控える必要があります。

モッキング手法は、クラス自体ではなく、クラスの外部依存関係に適用する必要があります。

プライベートメソッドのモックがクラスのテストに不可欠である場合、それは通常、悪い設計を示しています。

6. 結論

この簡単な記事では、PowerMockを使用して、テスト対象のクラスのプライベートメソッドのモックと検証のためにMockitoの機能を拡張する方法を示しました。

このチュートリアルのソースコードは、GitHubにあります。