概要
- Mockito 3 + JUnit 5 で基本的なモック化とテストをするサンプルコードを示す
- 今回の動作確認環境: Java 15 (AdoptOpenJDK 15.0.1+9) + Gradle 6.7 + Mockito 3.6.0 + JUnit 5.7.0 + macOS Catalina
サンプルコード
ソースコード一覧
├── build.gradle
└── src
├── main
│ └── java
│ ├── Client.java
│ └── Worker.java
└── test
└── java
└── ClientTest.java
build.gradle
ビルド・テスト実行用 Gradle 設定ファイル。
plugins {
id 'java'
}
repositories {
jcenter()
}
dependencies {
// Junit 5 を導入
// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'
// Mockito 3 を導入
// https://mvnrepository.com/artifact/org.mockito/mockito-core
testImplementation 'org.mockito:mockito-core:3.6.0'
// Mockito による JUnit 5 Extension ライブラリを導入
// https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter
testImplementation 'org.mockito:mockito-junit-jupiter:3.6.0'
}
test {
// JUnit platform を使う設定
useJUnitPlatform()
// テスト時の出力設定
testLogging {
// テスト時の標準出力と標準エラー出力を表示する
showStandardStreams true
// イベントを出力する (TestLogEvent)
events 'started', 'skipped', 'passed', 'failed'
// 例外発生時の出力設定 (TestExceptionFormat)
exceptionFormat 'full'
}
}
src/main/java/Worker.java
モック化の対象となるクラス。
public class Worker {
// 引数あり・戻り値ありメソッド
public int ariari(int x) {
throw new IllegalStateException("環境依存で発生するみたいな例外");
}
// 引数なし・戻り値なしメソッド
public void nasinasi() {
throw new IllegalStateException("環境依存で発生するみたいな例外");
}
}
src/main/java/Client.java
テスト対象のクラス。
public class Client {
private Worker worker = new Worker();
// 引数あり・戻り値ありメソッドを呼び出す
public int callAriari(int x) {
return worker.ariari(x * 2); // 2倍にした値を Worker#ariari に渡す
}
// 引数なし・戻り値なしメソッドを呼び出す
public int callNasinasi(int x) {
worker.nasinasi(); // Worker#nasinasi を呼び出す
return x * 2; // 2倍にした値を返す
}
}
src/test/java/ClientTest.java
テストクラス。
Worker クラスを Mockito 3 でモック化し、Client クラスのテストを JUnit 5 で実施する。
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@ExtendWith(MockitoExtension.class) // Mockito による JUnit 5 エクステンション
public class ClientTest {
// モックを注入するオブジェクト
@InjectMocks
private Client client = new Client();
// モック化するオブジェクト
@Mock
private Worker mockedWorker;
@Test
public void 引数あり_戻り値あり() {
// モックの振る舞い: Worker#ariari に 2 が渡されたときに 6 を返す
doReturn(6).when(mockedWorker).ariari(2);
// テスト: Client#callAriari に 1 を渡すとモックの Worker#ariari に 2 を渡して 6 が返ってくる
assertEquals(6, client.callAriari(1));
}
@Test
public void 引数なし_戻り値なし() {
// モックの振る舞い: Worker#nasinasi を呼び出したときに何もしない
doNothing().when(mockedWorker).nasinasi();
// テスト: Client#callNasinasi に 1 を渡すとモックの Worker#nasinasi を実行して 2 が返ってくる
assertEquals(2, client.callNasinasi(1));
}
@Test
public void 例外発生() {
// モックの振る舞い: Worker#ariari に 4 が渡されたときに例外を投げる
doThrow(new IllegalArgumentException("モック例外")).when(mockedWorker).ariari(4);
// テスト: Client#callAriari に 2 を渡すとモックの Worker#ariari に 4 を渡して例外が投げられる
IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> client.callAriari(2));
// テスト: 例外に想定したメッセージが含まれている
assertEquals("モック例外", e.getMessage());
}
@Test
public void 順次呼び出し() {
// モックの振る舞い: Worker#ariari に 6 が渡されたときに例外を2回投げたあと 18 を返す
doThrow(new IllegalArgumentException("モック例外1回目"))
.doThrow(new IllegalArgumentException("モック例外2回目"))
.doReturn(18)
.when(mockedWorker).ariari(6);
// テスト: Client#callAriari に 3 を渡すとモックの Worker#ariari に 6 を渡して例外が投げられる
IllegalArgumentException e1 = assertThrows(IllegalArgumentException.class, () -> client.callAriari(3));
assertEquals("モック例外1回目", e1.getMessage());
// テスト: Client#callAriari に 3 を渡すとモックの Worker#ariari に 6 を渡して例外が投げられる
IllegalArgumentException e2 = assertThrows(IllegalArgumentException.class, () -> client.callAriari(3));
assertEquals("モック例外2回目", e2.getMessage());
// テスト: Client#callAriari に 3 を渡すとモックの Worker#ariari に 6 を渡して 18 が返ってくる
assertEquals(18, client.callAriari(3));
}
}
テスト実行
Gradle で test タスクを実行した例。
$ gradle test
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :test
ClientTest > 引数なし_戻り値なし() STARTED
ClientTest > 引数なし_戻り値なし() PASSED
ClientTest > 引数あり_戻り値あり() STARTED
ClientTest > 引数あり_戻り値あり() PASSED
ClientTest > 例外発生() STARTED
ClientTest > 例外発生() PASSED
ClientTest > 順次呼び出し() STARTED
ClientTest > 順次呼び出し() PASSED
BUILD SUCCESSFUL in 19s
3 actionable tasks: 3 executed