PowerMockの紹介
1概要
モッキングフレームワークの助けを借りた単体テストは長い間有効な方法として認識されており、特にhttp://mockito.org/[Mockito]フレームワークは近年この市場を支配してきました。
そしてまともなコード設計を容易にし、パブリックAPIを単純にするために、いくつかの望ましい機能は意図的に除外されています。ただし、場合によっては、これらの欠点により、テスト担当者はモックの作成を実行可能にするためだけに面倒なコードを記述する必要があります。
これがhttps://github.com/jayway/powermock[PowerMock]フレームワークが登場するところです。
PowerMockito
は、MockitoをサポートするためのPowerMockの拡張APIです。これは、final、static、またはprivateメソッドをモックする機能の欠如など、Mockitoの問題を克服するための簡単な方法でJava Reflection APIと連携する機能を提供します。
このチュートリアルでは、PowerMockito APIとそれがテストにどのように適用されるかについて紹介します。
2 PowerMockito
によるテストの準備
PowerMockのMockitoサポートを統合する最初のステップは、Maven POMファイルに以下の2つの依存関係を含めることです。
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
次に、次の2つのアノテーションを適用して、
PowerMockito
を操作するためのテストケースを準備する必要があります。
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.** ")
@ PrepareForTest
アノテーションの
fullyQualifiedNames
要素は、モックしたいタイプの完全修飾名の配列を表します。
この場合、ワイルドカードを使用してパッケージ名を使用して、
PowerMockito
に、モック用に
com.baeldung.powermockito.introduction
パッケージ内のすべてのタイプを準備するよう指示します。
これで
PowerMockito
の機能を活用する準備が整いました。
3モックコンストラクタと最終メソッド
このセクションでは、
new
演算子を使ってクラスをインスタンス化するときに、実際のインスタンスではなく擬似インスタンスを取得し、そのオブジェクトを使って最終メソッドを擬似する方法を説明します。そのコンストラクタと最終メソッドがモックされるコラボレーションクラスは、次のように定義されています。
public class CollaboratorWithFinalMethods {
public final String helloMethod() {
return "Hello World!";
}
}
まず、
PowerMockito
APIを使用してモックオブジェクトを作成します。
CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);
次に、そのクラスの引数のないコンストラクタが呼び出されるたびに、実際のインスタンスではなくモックインスタンスが返されるようにするという期待を設定します。
whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);
デフォルトのコンストラクタを使用して
CollaboratorWithFinalMethods
クラスをインスタンス化することによって、このコンストラクションモックが実際にどのように機能するのかを確認してから、PowerMockの動作を確認します。
CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods();
verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();
次のステップでは、期待値を最終メソッドに設定します。
when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");
その後、このメソッドが実行されます。
String welcome = collaborator.helloMethod();
以下のアサーションは、
hellaMethod
メソッドが
collaborator
オブジェクトに対して呼び出されたことを確認し、モッキングの予想によって設定された値を返します。
Mockito.verify(collaborator).helloMethod();
assertEquals("Hello Baeldung!", welcome);
オブジェクト内のすべての最終メソッドではなく、特定の最終メソッドをモックしたい場合は、
Mockito.spy(T object)
メソッドが便利です。これはセクション5に示されています。
4静的メソッドのモック
CollaboratorWithStaticMethods.
という名前のクラスの静的メソッドをモックしたいとします。このクラスは次のように宣言されています。
public class CollaboratorWithStaticMethods {
public static String firstMethod(String name) {
return "Hello " + name + " !";
}
public static String secondMethod() {
return "Hello no one!";
}
public static String thirdMethod() {
return "Hello no one again!";
}
}
これらの静的メソッドをモックするために、囲むクラスを
PowerMockito
APIに登録する必要があります。
mockStatic(CollaboratorWithStaticMethods.class);
代わりに、次のセクションで示すように、
Mockito.spy(Class <T> class)
メソッドを使用して特定のメソッドをモックすることもできます。
次に、呼び出し時にメソッドが返す値を定義するために期待値を設定できます。
when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()))
.thenReturn("Hello Baeldung!");
when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");
あるいは、
thirdMethod
メソッドを呼び出すときに例外がスローされるように設定することができます。
doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class);
CollaboratorWithStaticMethods.thirdMethod();
それでは、最初の2つのメソッドを実行しましょう。
String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever");
String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");
実際のクラスのメンバーを呼び出す代わりに、上記の呼び出しはモックのメソッドに委任されています。次の表明は、モックが有効になったことを証明しています。
assertEquals("Hello Baeldung!", firstWelcome);
assertEquals("Hello Baeldung!", secondWelcome);
メソッドの呼び出し回数など、モックのメソッドの動作を確認することもできます。この場合、
firstMethod
は2回呼び出されていますが、
secondMethod
は決して呼び出されていません。
verifyStatic(Mockito.times(2));
CollaboratorWithStaticMethods.firstMethod(Mockito.anyString());
verifyStatic(Mockito.never());
CollaboratorWithStaticMethods.secondMethod();
-
注:**
PowerMockito
の静的メソッド検証の直前に
verifyStatic
メソッドを呼び出す必要があります。これは、連続したメソッド呼び出しが検証される必要があることを知るためです。
最後に、静的
thirdMethod
メソッドは、前のモックで宣言されているように
RuntimeException
をスローします。これは
@ Test
アノテーションの
expected
要素によって検証されます。
@Test(expected = RuntimeException.class)
public void givenStaticMethods__whenUsingPowerMockito__thenCorrect() {
//other methods
CollaboratorWithStaticMethods.thirdMethod();
}
5部分モッキング
クラス全体をモックする代わりに、
PowerMockito
APIでは
spy
メソッドを使用してその一部をモックすることができます。次のクラスは、部分的モッキングに対するPowerMockのサポートを説明するための共同作業者として使用されます。
public class CollaboratorForPartialMocking {
public static String staticMethod() {
return "Hello Baeldung!";
}
public final String finalMethod() {
return "Hello Baeldung!";
}
private String privateMethod() {
return "Hello Baeldung!";
}
public String privateMethodCaller() {
return privateMethod() + " Welcome to the Java world.";
}
}
上記のクラス定義で
staticMethod
という名前の静的メソッドをモックすることから始めましょう。まず、
PowerMockito
APIを使用して
CollaboratorForPartialMocking
クラスを部分的にモックし、その静的メソッドに期待値を設定します。
spy(CollaboratorForPartialMocking.class);
when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");
その後、静的メソッドが実行されます。
returnValue = CollaboratorForPartialMocking.staticMethod();
偽装動作は次のように検証されます。
verifyStatic();
CollaboratorForPartialMocking.staticMethod();
次のアサーションは、期待値に対して戻り値を比較することによって、モックメソッドが実際に呼び出されたことを確認します。
assertEquals("I am a static mock method.", returnValue);
それでは最後のプライベートメソッドに移りましょう。これらのメソッドの部分的なモックを説明するために、クラスをインスタンス化して
PowerMockito
APIに
spy
itを指定する必要があります。
CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking();
CollaboratorForPartialMocking mock = spy(collaborator);
上記で作成したオブジェクトは、ファイナルメソッドとプライベートメソッドの両方のモックを示すために使用されています。最後に期待値を設定してメソッドを呼び出し、メソッドを呼び出します。
when(mock.finalMethod()).thenReturn("I am a final mock method.");
returnValue = mock.finalMethod();
そのメソッドを部分的にモックする動作は証明されています。
Mockito.verify(mock).finalMethod();
テストでは、
finalMethod
メソッドを呼び出すと、期待値と一致する値が返されることを確認します。
assertEquals("I am a final mock method.", returnValue);
プライベートメソッドにも同様のプロセスが適用されます。主な違いは、テストケースからこのメソッドを直接呼び出すことができないことです。
基本的に、プライベートメソッドは同じクラスの他のメソッドによって呼び出されます。
CollaboratorForPartialMocking
クラスでは、
privateMethod
メソッドが
privateMethodCaller
メソッドによって呼び出され、後者をデリゲートとして使用します。期待と呼び出しから始めましょう。
when(mock, "privateMethod").thenReturn("I am a private mock method.");
returnValue = mock.privateMethodCaller();
プライベートメソッドのモックが確認されました。
verifyPrivate(mock).invoke("privateMethod");
次のテストでは、プライベートメソッドの呼び出しからの戻り値が期待値と同じであることを確認します。
assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);
6. 結論
このチュートリアルでは
PowerMockito
APIの概要を説明し、Mockitoフレームワークを使用するときに開発者が遭遇する問題のいくつかを解決するためのその使用法を示しました。
これらの例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/testing-modules/mockito[リンクされたGitHubプロジェクト]にあります。