JUnitとは、Javaで書いたコードが期待どおり動くかを自動で検証する、単体テスト(ユニットテスト)用のフレームワークです。「メソッドに2と3を渡したら5が返るか」といった小さな確認をコードとして書き、ボタン一つで何度でも実行できます。この記事では、JUnitの定義から、JUnit 5と4の違い、最新版、実際のテストの書き方までを実例で整理します。
まとめ:JUnitの要点
- 定義:Javaのコードをメソッドやクラスなどの最小単位(ユニット)で自動検証する、xUnit系の単体テストフレームワーク。
- 現在の主流はJUnit 5:Platform・Jupiter・Vintageの3モジュール構成。
@TestとassertEqualsなどのアサーションでテストを書く。 - 最新版:JUnit 6系が最新(6.0が2025年9月30日、以降6.1系。Java 17以上が必須)。Java 8〜16の環境ではJUnit 5系(現行メンテナンスは5.14系)を継続利用する。
- 使いどころ:ロジックのある処理・リファクタリング対象・回帰させたくない箇所に書く。単純なgetter/setterや外部依存だけの箇所に無理に書かない。
JUnitとは何か:単体テストを自動化するフレームワーク
JUnitは、Kent BeckとErich Gammaが開発したJava用のテスティングフレームワークで、SmalltalkのSUnitに端を発する「xUnit」系列の代表格です。単体テストとは、クラスやメソッドといった最小単位(ユニット)が単独で正しく動くかを確かめるテストを指します。JUnitはこの検証を「テストコード」として書き、実行結果を成功(緑)/失敗(赤)で即座に示します。
手作業でmainメソッドから動作を確かめる方法と違い、JUnitのテストは再現可能で、何度実行しても同じ結果になるように書くのが原則です。だからこそ、コードを修正した後に「以前動いていた機能が壊れていないか(回帰)」を毎回まとめて確認できます。単体テストの位置づけをより広い視点で捉えたい場合は、単体テストと結合テストの違いとGoogle流「テストサイズ」も参考になります。
テストを書く対象クラスに対応させて作るクラスを「テストクラス」と呼びます。慣習として本番コードと同じパッケージ構成の src/test/java 配下に置き、対象が Calculator なら CalculatorTest のように命名します。
JUnit 5と4の違い・最新バージョン
現在の標準はJUnit 5です。JUnit 4との最大の違いは、単一のjarだった4に対し、5が役割の異なる3つのモジュールに分かれたことです。
| モジュール | 役割 |
|---|---|
| JUnit Platform | テストを起動・実行する基盤(IDEやビルドツールが接続する層) |
| JUnit Jupiter | JUnit 5の新しいテストを書くためのAPIと実行エンジン |
| JUnit Vintage | 過去のJUnit 4/3のテストを5基盤上で動かす互換エンジン |
APIレベルでは、アノテーションのパッケージが org.junit(JUnit 4)から org.junit.jupiter.api(JUnit 5)へ変わり、テスト前後の処理を示すアノテーションも @Before/@After から @BeforeEach/@AfterEach に改称されました。新規プロジェクトはJUnit 5で書き、既存のJUnit 4資産はVintageで動かしつつ段階移行するのが定石です。
最新版とJavaバージョン要件
2025年9月30日にJUnit 6.0が公開されました。JUnit 6の要点は次の2つです。第一に、動作要件がJava 17以上へ引き上げられました(Spring Boot 3.x系などのLTS移行に合わせた変更)。第二に、これまでPlatform・Jupiter・Vintageで別々だったバージョン番号が統一され、依存関係の管理が簡単になりました。Java 8〜16を使う環境では、JUnit 6と並行してメンテナンスが続くJUnit 5系(現行は5.14系)を引き続き利用します。パッチ版は頻繁に更新されるため、正確な最新バージョンはJUnitの公式リリースページで確認してください。
JUnitの導入方法(Maven/Gradle)
JUnitはビルドツール経由で導入します。バージョンを個別指定する代わりに、公式が提供する junit-bom(Bill of Materials)でまとめて揃えると、モジュール間の版ずれを防げます。Mavenでは pom.xml に集約アーティファクト junit-jupiter を追加します。
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.14.4</version>
<scope>test</scope>
</dependency>
Gradle(Kotlin/Groovy DSL共通のGroovy記法)なら build.gradle に次の1行と、テスト実行をPlatformに委ねる設定を加えます。
testImplementation 'org.junit.jupiter:junit-jupiter:5.14.4'
test { useJUnitPlatform() }
IntelliJ IDEAやEclipseは近年のバージョンでJUnit 5を標準サポートしており、依存を追加すればテストクラス上の実行ボタンからそのまま動かせます。
基本的なテストの書き方
テストは「対象を呼び出し、結果をアサーションで検証する」の繰り返しです。最小のテストは、@Test を付けたメソッド1つで成立します。
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class CalculatorTest {
@Test
void add_2と3を渡すと5を返す() {
Calculator calc = new Calculator();
assertEquals(5, calc.add(2, 3));
}
}
テストメソッド名は「何をどうしたらどうなる」を日本語で書いても構いません。IDEのテスト結果一覧にそのまま表示され、仕様書の代わりになります。
よく使うアサーション
アサーションは org.junit.jupiter.api.Assertions の静的メソッド群です。用途で使い分けます。
| メソッド | 検証内容 |
|---|---|
| assertEquals(期待値, 実際値) | 2つの値が等しい |
| assertTrue / assertFalse | 条件がtrue/false |
| assertNull / assertNotNull | nullである/でない |
| assertThrows(例外.class, 処理) | 指定した例外が投げられる |
例外が起きること自体を検証したいときは assertThrows を使い、投げられた例外オブジェクトを受け取ってメッセージまで確認できます。
assertThrows(ArithmeticException.class,
() -> calc.divide(1, 0));
より流暢に書きたい場合は、別ライブラリのAssertJ(assertThat(result).isEqualTo(5).isPositive() のように連鎖できる)を併用する現場も多くあります。
テストのライフサイクル(@BeforeEach など)
複数のテストで共通の準備・後片付けがあるときは、ライフサイクルアノテーションで重複を減らします。
| アノテーション | 実行タイミング |
|---|---|
| @BeforeEach / @AfterEach | 各テストメソッドの前/後 |
| @BeforeAll / @AfterAll | クラス内の全テストの前/後に1回(static) |
| @Disabled | そのテストを一時的に無効化 |
private Calculator calc;
@BeforeEach
void setUp() {
calc = new Calculator();
}
パラメータ化・モックによるテストの効率化
パラメータ化テストで入力を一括検証
同じロジックを複数の入力で試すなら、テストメソッドを増やさず @ParameterizedTest でデータを差し替えます。境界値分析(最大値・最小値・0など)と相性がよく、少ない記述で網羅性を上げられます。
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ParameterizedTest
@ValueSource(ints = {2, 4, 100})
void 偶数判定(int n) {
assertTrue(n % 2 == 0);
}
Mockitoで依存をモックする
DBや外部APIに依存するクラスを、その依存を実際に動かさずに単体テストしたいときは、モックライブラリのMockitoを併用します。依存オブジェクトの振る舞いを when(...).thenReturn(...) で偽装し、対象クラスのロジックだけを切り出して検証できます。
UserRepository repo = mock(UserRepository.class);
when(repo.findName(1L)).thenReturn("Taro");
UserService service = new UserService(repo);
assertEquals("Taro", service.getName(1L));
モックを多用しすぎると「実装をなぞるだけで壊れやすいテスト」になりがちです。モックは外部依存の切り離しに絞り、ロジック本体は実物でテストするのが目安です。
テストを書く場所・書かない場所(判断の目安)
JUnitの使い方以上に迷うのが「どこまで書くか」です。カバレッジ(テストが通過したコードの割合)を100%にすること自体は目的ではありません。次の切り分けが実務的です。
- 書く:分岐や計算のあるロジック、バグを出したくない中核処理、リファクタリング予定の箇所、過去に不具合が出た箇所。
- 後回し・省略してよい:単純なgetter/setter、フレームワークが保証する定型コード、UIの見た目そのもの。
「まず失敗するテストを書いてから実装する」進め方に興味があればテスト駆動開発(TDD)の基礎を、テスト量の妥当性を数値で判断したい場合はバグ密度・テスト密度の目安(IPA基準値)が参考になります。入力値の設計観点はブラックボックステストとホワイトボックステストの違いで整理できます。
テストコードの初稿をAIに書かせる現場も増えている。GitHub Copilotでテストコードを自動生成する方法のように下書きは自動化できますが、「何を検証すべきか」の判断とアサーションの妥当性チェックは人間の役割として残ります。生成されたテストを鵜呑みにせず、意図した境界値・異常系を押さえているかを必ずレビューしてください。
よくある質問
JUnitとは一言で何ですか?
Javaのコードが正しく動くかをコードで自動検証する、単体テスト用のフレームワークです。テストを何度でも同じ条件で実行でき、修正による機能の後退を早期に発見できます。
JUnit 4と5、どちらを使うべきですか?
新規開発はJUnit 5(Jupiter)を選びます。既存のJUnit 4資産はVintageエンジンで動かしながら、段階的に5へ移行するのが安全です。
JUnitの最新版は?
JUnit 6系が最新で(6.0が2025年9月30日リリース、以降6.1系)、Java 17以上が必須です。Java 16以下の環境ではJUnit 5系(現行は5.14系)を使います。パッチ版は更新が速いため、正確な番号は公式リリースページで確認してください。
JUnitでテストが失敗したときはどうデバッグしますか?
失敗したテストにはIDEでブレークポイントを置き、テストクラスをデバッグ実行します。テストメソッド単位で切り離して実行できるため、対象を最小化して変数の値をステップ確認でき、原因の特定が速くなります。
テストクラスはどこに置きますか?
本番コードと同じパッケージ構成で src/test/java 配下に置きます。対象クラス名に「Test」を付けた命名(CalculatorTest など)が一般的です。