🕒 学習時間
19:30~20:00
🧑💻 実施した学習内容
1. 疑問点
JUnit5とAssertionとAssertJの特徴を役割、機能性、メソッド、インターフェイスの違い
2. 技術の概要
◾️何をするものか
-
JUnit5
- Javaのテスト実行フレームワーク
- 「テストを動かす仕組み」
- テストライフサイクル管理や実行制御を担当
-
Assertion(JUnit Assertions)
- テスト結果を検証する機能
- 「期待値と実際の値を比較する仕組み」
- JUnit5に標準搭載
-
AssertJ
- 高機能なアサーションライブラリ
- 「読みやすく柔軟な検証を書くためのライブラリ」
- JUnit5とは別製品
◾️背景・目的(なぜ必要か)
ソフトウェア開発では、以下の問題が発生する。
- 修正したら別機能が壊れる(リグレッション)
- 人間の手動確認では漏れが発生する
- 大規模化すると確認コストが爆発する
- Nullや境界値バグが頻発する
そこで、
-
JUnit5
→ テスト自動化を行う -
Assertion
→ 「正しいか」を判定する -
AssertJ
→ より読みやすく保守しやすい検証を書く
という役割分担になっている。
3. 内容
全体像
JUnit5
├─ テストを実行する
├─ テスト管理を行う
└─ Assertionsを提供
Assertions(JUnit標準)
└─ 基本的な検証機能
AssertJ
└─ 高機能で読みやすい検証ライブラリ
JUnit5とは
JUnit5は「テスト実行基盤」。
主な役割:
- テスト実行
- テストライフサイクル管理
- パラメータ化テスト
- 繰り返しテスト
- 拡張機能
- テスト順制御
代表アノテーション:
@Test
@BeforeEach
@AfterEach
@DisplayName
@ParameterizedTest
@RepeatedTest
JUnit5単体では、
「実行」は得意だが、
「表現力の高い検証」は弱い。
Assertion(JUnit標準)とは
JUnit5標準の検証機能。
パッケージ:
org.junit.jupiter.api.Assertions
例:
assertEquals(10, actual);
assertTrue(result);
assertThrows(Exception.class, () -> method());
特徴:
- シンプル
- 標準搭載
- 学習コスト低い
- 小規模向け
ただし、
複雑なオブジェクト比較になると可読性が悪化する。
AssertJとは
AssertJはFluent Interface(流れるようなAPI)を採用したアサーションライブラリ。
例:
assertThat(user.getName())
.startsWith("T")
.endsWith("o");
特徴:
- 非常に読みやすい
- メソッドチェーン可能
- IDE補完が強力
- コレクション検証が強い
- 例外検証が柔軟
実務ではかなり人気。
特にSpring Bootではよく使われる。
なぜAssertJが人気なのか
背景にはJUnit Assertionの弱点がある。
JUnit Assertion:
assertTrue(user.getName().startsWith("T"));
問題:
- 条件が長いと読みにくい
- エラー原因が分かりにくい
- IDE補完が弱い
AssertJ:
assertThat(user.getName())
.startsWith("T");
こちらは:
- 英文のように読める
- エラー内容が詳細
- 補完で使えるメソッドが見える
保守性が高い。
4. 用語定義
| 用語 | 意味 |
|---|---|
| テストフレームワーク | テスト実行基盤 |
| Assertion | 検証処理 |
| Fluent Interface | メソッドチェーンで自然言語風に書く設計 |
| テストケース | 1つの検証単位 |
| アサーション失敗 | 期待値と実際値が異なる状態 |
5. 解決する課題・メリット
| 技術 | 解決する課題 |
|---|---|
| JUnit5 | テスト自動化 |
| Assertion | 正しい結果か検証 |
| AssertJ | 可読性・保守性向上 |
AssertJの強み
特に以下が強い。
- Collection検証
- Optional検証
- Stream検証
- 例外検証
- 再帰比較
- フィールド抽出
例:
assertThat(users)
.extracting(User::getName)
.contains("Tanaka");
これはJUnit標準ではかなり書きづらい。
6. 使用する注意事項・デメリット
| 技術 | デメリット |
|---|---|
| JUnit Assertions | 表現力が弱い |
| AssertJ | 学習コスト増加 |
| AssertJ | 外部ライブラリ依存 |
| JUnit5 | Assertion機能は最低限 |
注意点
AssertJを導入すると:
assertEquals
assertTrue
assertFalse
よりも
assertThat
中心になる。
チーム内で統一しないと、
コードスタイルが混在する。
7. 類似技術との比較
| 項目 | JUnit5 | JUnit Assertions | AssertJ |
|---|---|---|---|
| 役割 | テスト実行 | 検証 | 高機能検証 |
| 提供元 | JUnit | JUnit | AssertJ |
| 標準搭載 | ○ | ○ | × |
| 可読性 | 中 | 低〜中 | 高 |
| IDE補完 | 中 | 弱い | 強い |
| メソッドチェーン | × | × | ○ |
| コレクション検証 | 弱い | 弱い | 強い |
| Optional対応 | 弱い | 弱い | 強い |
| Stream対応 | 弱い | 弱い | 強い |
| 実務人気 | 非常に高い | 高い | 非常に高い |
8. 基本的な使い方・実装(サンプルコード)
JUnit Assertions
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class UserTest {
@Test
void 名前検証() {
String actual = "Taro";
// expected, actual の順で比較
assertEquals("Taro", actual);
// 条件判定
assertTrue(actual.startsWith("T"));
}
}
コード解説
assertEquals
→ 値比較
assertTrue
→ boolean判定
JUnit標準のみで完結。
AssertJ版
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;
class UserTest {
@Test
void 名前検証() {
String actual = "Taro";
// Fluent Interfaceで自然言語風に書ける
assertThat(actual)
.startsWith("T")
.endsWith("o")
.hasSize(4);
}
}
コード解説
assertThat(actual)
→ actualを起点に検証開始
startsWith
→ 前方一致
endsWith
→ 後方一致
hasSize
→ 文字数検証
9. まとめ表
JUnit5 / Assertions / AssertJ 比較表
| 比較項目 | JUnit5 | JUnit Assertions (org.junit.jupiter.api.Assertions) |
AssertJ (org.assertj.core.api.Assertions) |
|---|---|---|---|
| 役割 | テスト実行フレームワーク | JUnit標準の検証API | Fluent API型の高機能検証ライブラリ |
| 主な目的 | テスト管理・実行・ライフサイクル制御 | 値の正誤判定 | 可読性の高い柔軟な検証 |
| 主な用途 | テスト全体を構築 | シンプルな比較・例外確認 | 複雑なオブジェクト検証 |
| 導入 | SpringBoot標準搭載が多い | JUnit5に含まれる | 追加依存が必要 |
| 記述スタイル | アノテーション中心 | staticメソッド呼び出し | メソッドチェーン |
| 可読性 | 中 | 普通 | 高い |
| 学習コスト | 中 | 低 | 中〜高 |
| 柔軟性 | 高 | 低〜中 | 非常に高い |
| エラーメッセージ | 基本的 | シンプル | 詳細で見やすい |
| 主な対象 | テスト制御 | 単純検証 | 高度検証 |
| null検証 | 可能 | assertNull() |
isNull() |
| コレクション検証 | 最低限 | やや弱い | 非常に強い |
| 例外検証 |
@Test + assertThrows()
|
assertThrows() |
assertThatThrownBy() |
| DTO/Entity比較 | 手動比較が多い | 項目単位比較 | 再帰比較可能 |
| チェーン記法 | なし | なし | あり |
| 拡張性 | Extension Modelあり | 少ない | 非常に高い |
代表アノテーション比較
| 分類 | JUnit5 |
|---|---|
| テスト実行 | @Test |
| 初期化 | @BeforeEach |
| 後処理 | @AfterEach |
| 全体初期化 | @BeforeAll |
| 全体後処理 | @AfterAll |
| パラメータテスト | @ParameterizedTest |
| 条件付き実行 | @EnabledOnOs |
| タグ管理 | @Tag |
| ネストテスト | @Nested |
| 表示名変更 | @DisplayName |
Assertions と AssertJ のメソッド比較
| 機能 | JUnit Assertions | AssertJ |
|---|---|---|
| 等価比較 | assertEquals(a, b) |
assertThat(a).isEqualTo(b) |
| 真偽判定 | assertTrue() |
isTrue() |
| null確認 | assertNull() |
isNull() |
| 非null確認 | assertNotNull() |
isNotNull() |
| 配列比較 | assertArrayEquals() |
containsExactly() |
| 例外確認 | assertThrows() |
assertThatThrownBy() |
| 全件検証 | assertAll() |
satisfies() |
| 文字列比較 | 基本のみ |
startsWith(), contains() 等 |
| サイズ比較 | 手動 | hasSize() |
| Optional検証 | 弱い | isPresent() |
| Stream検証 | 弱い | 強い |
| List抽出検証 | 手動ループ | extracting() |
| オブジェクト比較 | 項目単位 | usingRecursiveComparison() |
インターフェイス・構造の違い
| 項目 | JUnit Assertions | AssertJ |
|---|---|---|
| ベース構造 | static utility class | Fluent Interface |
| 呼び出し方式 | 関数型 | メソッドチェーン |
| IDE補完 | 少なめ | 非常に強い |
| 型安全性 | 普通 | 高い |
| 拡張クラス | 少ない | 豊富 |
| カスタム検証 | 作りづらい | 作りやすい |
実務での使い分け
| シーン | 推奨 |
|---|---|
| 簡単な単体テスト | JUnit Assertions |
| DTO比較 | AssertJ |
| REST APIレスポンス検証 | AssertJ |
| List/Map検証 | AssertJ |
| 学習初期 | JUnit Assertions |
| 実務レベル | AssertJ推奨 |
| SpringBoot開発 | JUnit5 + AssertJ の組み合わせ |
10. 根拠の掲示
◾️[公式ドキュメント]
-
JUnit5 User Guide
-
AssertJ Official
-
Maven Repository JUnit
-
Maven Repository AssertJ
11. 次やりいたいこと
- assertEquals系を試す
- AssertJのassertThatを重点学習
- Collection検証を学ぶ
- Exception検証を学ぶ
- Mockitoとの組み合わせを学ぶ
- SpringBoot + MockMvc + AssertJを学ぶ
- カスタムAssert作成を学ぶ