🕒 学習時間
13:30~14:00
🧑💻 実施した学習内容
1. 疑問点
JUnit5の標準機能と拡張機能で使えるアノテーションやメソッド、役割の違いについて
2. 技術の概要
◾️何をするものか
JUnit5はJavaのテストフレームワークです。
JUnit5では大きく3つの構成があります。
| 構成 | 役割 |
|---|---|
| JUnit Platform | テスト実行基盤 |
| JUnit Jupiter | JUnit5本体(標準機能) |
| JUnit Vintage | JUnit4互換 |
今回重要なのは「JUnit Jupiter」です。
JUnit5では、
- 標準機能(Core API)
- 拡張機能(Extension API)
が明確に分離されています。
◾️背景・目的(なぜ必要か)
JUnit4時代には問題がありました。
特に以下です。
| JUnit4の問題 | 内容 |
|---|---|
| 機能追加が難しい | Runnerが1つしか使えない |
| Ruleが複雑 | TestRule / MethodRuleが分裂 |
| DIしにくい | パラメータ注入が弱い |
| 柔軟性不足 | ライブラリ統合が困難 |
例えば:
@RunWith(SpringRunner.class)
を使うと、
別Runner(Mockitoなど)を同時利用できませんでした。
つまり、
- Spring用Runner
- Mockito用Runner
- DB用Runner
を同時利用できない問題がありました。
そこでJUnit5では、
「Extension API」
として統一されました。
これにより:
- SpringExtension
- MockitoExtension
- SeleniumExtension
などを同時利用可能になりました。
3. 内容
まず結論
JUnit5には2種類ある。
| 種類 | 用途 |
|---|---|
| 標準機能 | テストを書く |
| 拡張機能 | テスト実行を拡張する |
① 標準機能(JUnit Jupiter Core)
これはJUnit5が最初から持つ機能。
主に:
- テスト定義
- ライフサイクル
- パラメータテスト
- アサーション
を担当する。
標準アノテーション一覧
| アノテーション | 役割 |
|---|---|
| @Test | 通常テスト |
| @BeforeEach | 各テスト前 |
| @AfterEach | 各テスト後 |
| @BeforeAll | 全テスト前 |
| @AfterAll | 全テスト後 |
| @DisplayName | 表示名 |
| @Nested | ネストテスト |
| @Disabled | テスト無効 |
| @Tag | タグ付け |
| @RepeatedTest | 繰り返しテスト |
| @ParameterizedTest | パラメータテスト |
| @TestFactory | 動的テスト |
| @TestMethodOrder | 実行順制御 |
標準メソッド一覧
Assertions
assertEquals()
assertTrue()
assertFalse()
assertThrows()
assertAll()
assertTimeout()
役割:
テスト結果検証。
Assumptions
assumeTrue()
assumeFalse()
役割:
条件不一致ならテストスキップ。
CI/CDでよく使う。
② 拡張機能(Extension API)
ここがJUnit5最大の特徴。
拡張機能は:
「JUnitの動きを横からカスタマイズする仕組み」
である。
使用アノテーション
| アノテーション | 役割 |
|---|---|
| @ExtendWith | 拡張登録 |
| @RegisterExtension | 動的登録 |
Extensionインターフェース一覧
| Interface | 役割 |
|---|---|
| BeforeEachCallback | beforeEach介入 |
| AfterEachCallback | afterEach介入 |
| BeforeAllCallback | beforeAll介入 |
| AfterAllCallback | afterAll介入 |
| ParameterResolver | DI |
| TestWatcher | 成功失敗監視 |
| ExecutionCondition | 実行条件制御 |
| InvocationInterceptor | メソッド横取り |
| TestInstancePostProcessor | インスタンス加工 |
イメージ
標準機能
@Test
→ テストを実行する
これは「利用者側API」。
拡張機能
@BeforeEachの前後に処理を差し込む
これは「フレームワーク拡張API」。
つまり:
| 視点 | 役割 |
|---|---|
| 標準機能 | テストを書く |
| 拡張機能 | JUnitを改造する |
実務で超重要な拡張
| 拡張 | 用途 |
|---|---|
| MockitoExtension | Mock自動生成 |
| SpringExtension | Spring統合 |
| SeleniumExtension | Selenium統合 |
| DBUnitExtension | DBテスト |
なぜExtensionが強いのか
JUnit4:
@RunWith(SpringRunner.class)
1個しか使えない。
JUnit5:
@ExtendWith({
SpringExtension.class,
MockitoExtension.class
})
複数利用可能。
これが革命だった。
4. 用語定義
| 用語 | 意味 |
|---|---|
| テストライフサイクル | テスト前後処理 |
| アサーション | 結果検証 |
| Extension | JUnit拡張 |
| Callback | 特定タイミング処理 |
| ParameterResolver | DI機構 |
| Dynamic Test | 実行時生成テスト |
5. 解決する課題・メリット
| 課題 | 解決 |
|---|---|
| Runner競合 | Extension統一 |
| テスト共通化困難 | Callback対応 |
| Mock注入が面倒 | ParameterResolver |
| 柔軟性不足 | Extension API |
特に実務メリット
SpringBoot
@ExtendWith(SpringExtension.class)
でDI可能。
Mockito
@Mock
@InjectMocks
自動初期化。
テスト自動化
CI/CDで:
- DB初期化
- Docker起動
- Selenium管理
まで可能。
6. 使用する注意事項・デメリット
| 注意点 | 内容 |
|---|---|
| 学習コスト高い | Callback種類が多い |
| 過剰拡張危険 | ブラックボックス化 |
| ライフサイクル理解必要 | 実行順バグ発生 |
| Extension乱用 | 可読性低下 |
アンチパターン例
@ExtendWith(HugeGodExtension.class)
全部入りExtension。
何してるか分からなくなる。
7. 類似技術との比較
| 技術 | 特徴 | 問題 |
|---|---|---|
| JUnit4 Runner | クラス単位拡張 | 1つしか使えない |
| JUnit4 Rule | メソッド拡張 | 複雑 |
| JUnit5 Extension | 統一API | 学習必要 |
| TestNG Listener | 高機能 | Java標準から離れる |
8. 基本的な使い方・実装(サンプルコード)
import org.junit.jupiter.api.*;
class CalculatorTest {
// 各テスト前に実行
@BeforeEach
void setup() {
System.out.println("setup");
}
// テスト本体
@Test
void addTest() {
int result = 1 + 2;
// 結果検証
Assertions.assertEquals(3, result);
}
// 各テスト後
@AfterEach
void cleanup() {
System.out.println("cleanup");
}
}
◾️コード例の解説
処理順:
@BeforeEach
↓
@Test
↓
@AfterEach
JUnitはこのライフサイクルで動く。
良い例
@ExtendWith(DatabaseExtension.class)
@ExtendWith(MockitoExtension.class)
@ExtendWith(LogExtension.class)
責務分離。
9. まとめ
JUnit5 標準機能(Core機能)
| 分類 | アノテーション / メソッド | 役割 | 特徴 | 主な用途 |
|---|---|---|---|---|
| テスト実行 | @Test |
テストメソッド定義 | 最も基本のテスト定義 | 単体テスト |
| 繰り返し | @RepeatedTest |
同じテストを複数回実行 | 回数指定可能 | ランダム値検証 |
| パラメータ化 | @ParameterizedTest |
引数を変えて実行 | データ駆動テスト | バリデーション確認 |
| CSV入力 | @CsvSource |
CSV形式の値を渡す | 簡易データ定義 | 複数パターン確認 |
| 外部CSV | @CsvFileSource |
CSVファイルから取得 | テストデータ分離 | 大量データ検証 |
| 値入力 | @ValueSource |
単一型配列を渡す | シンプル | null以外検証 |
| Null入力 | @NullSource |
null値注入 | nullテスト簡略化 | NullPointer対策 |
| Enum入力 | @EnumSource |
Enum全件または一部投入 | Enum向け | ステータス確認 |
| 条件付き | @EnabledOnOs |
OS条件で実行 | 環境依存対応 | Windows限定処理 |
| 条件付き | @DisabledOnOs |
OS条件で無効化 | 実行制御可能 | Linux非対応回避 |
| 無効化 | @Disabled |
テスト停止 | 一時的に無効化 | 未完成テスト |
| 事前処理 | @BeforeEach |
各テスト前実行 | 毎回初期化 | 객체生成 |
| 事後処理 | @AfterEach |
各テスト後実行 | クリーンアップ | 接続解放 |
| 全体事前 | @BeforeAll |
全テスト前に1回 | static必要 | DB接続 |
| 全体事後 | @AfterAll |
全テスト後に1回 | static必要 | 後始末 |
| グループ化 | @Nested |
テストを階層化 | 可読性向上 | 条件別整理 |
| 表示名 | @DisplayName |
テスト名変更 | 日本語利用可 | レポート改善 |
| タグ付け | @Tag |
カテゴリ分類 | build連携可能 | slow/fast分類 |
| タイムアウト | assertTimeout() |
制限時間確認 | 非同期可 | 性能確認 |
| 例外確認 | assertThrows() |
例外検証 | 型安全 | 異常系テスト |
| 全検証 | assertAll() |
複数assertまとめ実行 | 失敗を一括表示 | DTO検証 |
| 条件検証 | Assertions.assertEquals() |
値比較 | 基本assert | 正常系確認 |
| 真偽確認 | Assertions.assertTrue() |
true確認 | 条件式検証 | 判定確認 |
| Null確認 | Assertions.assertNull() |
null確認 | null判定 | 初期値確認 |
JUnit5 拡張機能(Extension機能)
| 分類 | アノテーション / メソッド | 役割 | 特徴 | 主な用途 |
|---|---|---|---|---|
| 拡張登録 | @ExtendWith |
拡張機能追加 | JUnit5の中心拡張 | Mockito/Spring連携 |
| ライフサイクル | BeforeEachCallback |
テスト前フック | Extension API | 共通前処理 |
| ライフサイクル | AfterEachCallback |
テスト後フック | Extension API | 後処理 |
| ライフサイクル | BeforeAllCallback |
全体前処理 | 初期化用途 | DB準備 |
| ライフサイクル | AfterAllCallback |
全体後処理 | リソース解放 | 接続終了 |
| 条件判定 | ExecutionCondition |
実行条件制御 | 独自条件可能 | 環境依存 |
| 例外制御 | TestExecutionExceptionHandler |
例外横取り | 独自ログ可能 | エラー解析 |
| パラメータ注入 | ParameterResolver |
引数DI | Spring風注入 | 共通オブジェクト |
| テスト監視 | TestWatcher |
成功/失敗監視 | ログ用途 | レポート |
| インスタンス生成 | TestInstanceFactory |
テスト生成制御 | DI連携向け | 特殊生成 |
| 実行順制御 | MethodOrderer |
テスト順変更 | 任意順序化 | 状態依存確認 |
| Mockito連携 | MockitoExtension |
Mock初期化 |
@Mock利用可能 |
モックテスト |
| Spring連携 | SpringExtension |
Spring DI連携 |
@Autowired有効 |
SpringBootテスト |
| 一時ディレクトリ | @TempDir |
一時フォルダ生成 | 自動削除 | ファイルテスト |
| テスト情報 | TestInfo |
メタ情報取得 | テスト名取得 | ログ出力 |
| レポート | TestReporter |
レポート出力 | key-value形式 | デバッグ |
| 動的テスト | @TestFactory |
実行時テスト生成 | Stream利用可 | 大量ケース生成 |
| テンプレート | @TestTemplate |
共通テスト定義 | Provider必要 | 汎用試験 |
| 並列実行 | @Execution |
並列設定 | パフォーマンス向上 | CI高速化 |
標準機能 と 拡張機能 の違い
| 比較項目 | 標準機能 | 拡張機能 |
|---|---|---|
| 提供元 | JUnit5本体 | 外部連携 + カスタマイズ |
| 主目的 | テストを書く | テスト実行を拡張する |
| 難易度 | 初学者向け | 中〜上級者向け |
| 主な対象 | assert / test実行 | DI / Mock / Hook |
| カスタマイズ性 | 低い | 高い |
| 利用頻度 | 非常に高い | フレームワーク依存 |
| 代表例 |
@Test assertEquals
|
@ExtendWith |
| 実務利用 | 必須 | Spring/Mockitoで頻出 |
| 依存関係 | JUnit単体 | Mockito/Spring等 |
| イメージ | 「テストを書く道具」 | 「テストを強化するアダプタ」 |
実務でよく使う組み合わせ例
| 構成 | 用途 |
|---|---|
@Test + assertEquals |
基本単体テスト |
@ParameterizedTest + @CsvSource |
入力パターン試験 |
@ExtendWith(MockitoExtension.class) |
Mock利用 |
@SpringBootTest + SpringExtension |
Spring統合試験 |
assertThrows |
異常系テスト |
@BeforeEach |
テスト初期化 |
@Nested |
条件別整理 |
@Tag("slow") |
CIテスト分類 |
10. 根拠の掲示
◾️[公式ドキュメント]
-
JUnit5 User Guide
JUnit 5 User Guide -
Extension Model
JUnit5 Extension Model
◾️[参考にした記事]
-
JUnit5 公式ガイド(5.10)
:contentReference[oaicite:2]{index=2} -
JUnit5 Extension概要
:contentReference[oaicite:3]{index=3} -
JUnit4→5移行議論
:contentReference[oaicite:4]{index=4}
11. 次やること
次に学ぶと理解がかなり深くなる。
- MockitoExtension
- SpringExtension
- ParameterResolver
- TestWatcher
- BeforeEachCallback
- InvocationInterceptor
- カスタムExtension作成
- JUnit4 Runnerとの違い
- JUnit5内部実装(Engine構造)
- Testcontainers + JUnit5