自動テストツール JUnit Mockito/PowerMockito

Mockitoとは

Publicメソッドのテスト、Publicメソッド内のメソッドのMock化が可能

PowerMockitoとは

Privateメソッド、Staticメソッドのテストが可能なMockitoの拡張版
Powermockitoを使用する場合もMockitoは使用する。
Mock化、Spy化の手順がMockitoと異なる。
ここではPowerMockitoを使用する前提での手順を記載する

Mock

Mockとは

本番環境で外部のサーバに接続する様な処理に対して、
TEST環境では外部サーバに接続できず必ず失敗してしまうが、
その処理が成功したとしてテストを行いたい場合に使用。
外部接続処理をMockと呼ぶ

Mock化

通常
@Mock
praivete TestClass mock;

newできない場合
Mockアノテーションは自動的にnewされてインスタンスが生成される為、newできない場合は失敗する
クラス内で外部を参照するstatic変数を宣言している等
その場合はクラス内のstatic変数を先にmock化する必要あり

TestClassクラス内のstatic変数を先にmock化する処理
TestClass mock = PowerMockito.mock(new TestClass());

Spyとは

テスト対象メソッド自体は実行、メソッド内の一部をMock化する場合のMock

テストクラスに記述
@RunWith(PowerMockRunner.class)
@PrepareForTest({TestClass.class, 他.class})
public class AppTest { ~

Spy化

通常
@Spy
private TestClass spy = new TestClass();

TestClassのnewができない場合
TestClassへの事前処理
TestClass mock = PowerMockito.spy(new TestClass());

Publicメソッド

Mockito.doReturn(戻り値).when(mock).メソッド名(メソッド引数);

Publicメソッド(Void型)

Mockito.doNothing().when(mock).メソッド名(メソッド引数);
Mockito.doNothing().when(mock).メソッド名(Mockito.any(クラス名.class));

インスタンスをMockで取得

テスト対象のメソッド内等でインスタンス化が実行され、インスタンスメソッドを呼ぶ処理をテストする場合
PowerMockito.whenNew(クラス名.class).withNoArguments().thenReturn(mock);
PowerMockito.whenNew(クラス名.class).withArguments(anyString()).thenReturn(mock);
PowerMockito.whenNew(クラス名.class).withArguments(anyInt()).thenReturn(mock);

Privateメソッド

PowerMockito.doNothing().when(mock,"メソッド名", メソッド引数);
PowerMockito.doReturn(戻り値).when(mock,"メソッド名", メソッド引数);

Staticメソッド

テストクラスに記述
@RunWith(PowerMockRunner.class)
@PrepareForTest({Staticメソッドのクラス.class, 他.class})
public class AppTest { ~

PowerMockito.mockStatic(Staticメソッドのクラス.class);
PowerMockito.when(Staticメソッド()).thenReturn(Staticメソッド戻り値);

Static&Privateメソッド

テストクラスに記述
@RunWith(PowerMockRunner.class)
@PrepareForTest({Staticメソッドのクラス.class, 他.class})
public class AppTest { ~

PowerMockito.spy(Staticクラス.class);
PowerMockito.doReturn(戻り値).when(Staticクラス.class, "メソッド名", 引数);

Setter無しのPrivateフィールド

インスタンスをMock化 「インスタンスをMockで取得」参照
PowerMockito.whenNew(クラス名.class).withNoArguments().thenReturn(mock);
MockのPrivateフィールド(Setter無し)に値をセット
Whitebox.setInternalState(mock, "privateフィールド名", 設定値);

Mockの挙動も指定

PowerMockito.doAnswer(invocation -> {
 メソッド内部の挙動
 return Void.TYPE;
}).when(mock, "メソッド名", メソッド引数);

Mock引数の簡略化

Mockito.Any(String.class)
Mockito.Any(List.class)
List<Test>等の場合

テスト実行

mockはスパイ

Publicメソッドの実行

戻り値 = mock.メソッド名(メソッド引数);

Privateメソッドの実行

通常
java.lang.reflect
Method method = TestClass.class.getDeclaredMethod("プライベートメソッド名", メソッド引数のクラス.class);
method.setAccessible(true);
戻り値 = method.invoke(mock, メソッド引数);

テスト対象メソッドの中のプライベートメソッドを更にMock化する場合
Whitebox.invokeMethod(mock, "プライベートメソッド名", メソッド引数);

Getter無しのPrivateフィールドの値取得

java.lang.reflect
Test test = new Test();
Field field = test.getClass().getDeclaredField("privateフィールド名");
field.setAccessible(true);

"privateフィールド名"の値を取得
String actual = String.valueOf(field.get(test));

テスト結果の検証

値の比較

import static org.hamcrest.CoreMatchers.is;

Assert.assertThat(actualValue, is(expectValue));

リストの比較

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.samePropertyValuesAs;

Assert.assertThat(actualList, is(samePropertyValuesAs(expectList));

publicメソッドの実行回数

Mockito.verify(mock, times(0)).メソッド名(メソッド引数);
Mockito.verify(mock, times(1)).メソッド名(メソッド引数);

Privateメソッドの実行回数

PowerMockito.verifyPrivate(mock, times(0)).invoke("メソッド名", メソッド引数);
PowerMockito.verifyPrivate(mock, times(1)).invoke("メソッド名", メソッド引数);

失敗

try {
 例外が発生する事を検証する場合
 mock.メソッド();

 処理されなければOK
 Assert.fail();
} catch(Exception e) {
 ~
}

Follow me!

前の記事

GCP 主なサービス

次の記事

Java8 Optional