PowerMockを使ったプライベートメソッドのモッキング

1概要

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

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

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

それはバイトコード操作と完全に別のクラスローダーに頼ることによってそれを行います。

2 Mavenの依存関係

まず、MockitoとJUnitでPowerMockを使用するために必要な依存関係を 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>

最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22powermock-module-junit4%22[here]およびhttps://search.maven.org/で確認できます。 %7Cga%7C1%7Ca%3A%22powermock-api-mockito2%22[こちら]。

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());

この場合、privateメソッドをモックして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の機能を拡張し、テスト対象クラスのプライベートメソッドをモックして検証する方法を説明しました。

このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/testing-modules/mockito[over on GitHub]にあります。