「動くことは動く。でも、直したところが他を壊していないか、実は自信がない」。そう感じたことがあるなら、原因はテストがないことだ。
JUnit5を使えば、@Testと数行のアサーションだけで、この不安を毎回機械的に確認できるようになる。
JUnit5の使い方は、(1) Maven/Gradleに依存関係を追加する、(2) src/test/javaに@Test付きのテストクラスを書く、(3) mvn testかIDEで実行して結果を確認する、の3ステップだ。
この記事では3ステップを順に解説したうえで、例外テスト・Arrange-Act-Assertによるテスト設計・Mockitoを使ったモック化まで、実務でそのまま使える形で扱う。
JUnit4からの変更点も押さえているので、既存プロジェクトでの移行判断にも使える。
この記事でわかること
- JUnit5の導入方法(Maven/Gradle)
- @Test・アサーション・例外テストの基本的な書き方
- mvn test・gradle test・IDEでのテスト実行方法
- Arrange-Act-Assertパターンによるテスト設計
- @BeforeEach・@ParameterizedTest・@Nestedなどの便利機能
- Mockitoを使ったモックテストの基礎
PARTS LIST /目次
JUnit5の書き方早見表(コピペ用)
テストを書くたびに「あのアノテーション、何だっけ」となるものを1つの表にまとめた。ブックマークしておけば、次からはこの表だけで足りる。
assertEquals 以外のアサーション(assertAll・assertTimeout など)は、JUnit assertメソッド一覧の早見表にまとめてある。
JUnit5とは?JUnit4との違いも解説
JUnitは、Javaのユニットテスト(単体テスト)を書いて実行するためのフレームワークです。Javaのテストツールとして最も広く使われています。
ユニットテストの目的と重要性
ユニットテストの目的は、クラスやメソッドといったプログラムの最小単位(ユニット)が、それぞれ正しく動くかを確かめることです。
ユニットテストを導入するメリットは主に3つです。
メリット
- 品質の向上: バグを開発の早い段階で発見し、修正できます。
- リファクタリングの促進: テストコードがあれば、コードを修正した際に意図しない不具合(デグレード)が発生していないかを即座に確認できます。
- 仕様のドキュメント化: よく書かれたテストコードは、そのコードが「どのように動くべきか」を示す生きたドキュメントです。
この「仕様のドキュメント化」というメリットは、筆者自身、前任者が退職しドキュメントがほぼゼロの状態でシステムを引き継いだときに実感したことだ。
仕様書はなく、頼れるのはコードだけ。
それでもテストコードが残っていたクラスは、半年かけての引き継ぎ作業の中でも「どう動くべきか」が読むだけでわかり、把握のスピードが明らかに違った。
テストコードがなければ、仕様の把握はもっと長引いていたはずだ。
JUnitの概要とバージョンの違い(JUnit4とJUnit5)
JUnitにはいくつかのバージョンがありますが、現在主流なのはJUnit5です。以前はJUnit4が広く使われていました。
JUnit4とJUnit5では、アーキテクチャとアノテーション名が大きく変わりました。
例えば、テスト前の初期化処理は、JUnit4では@Beforeでしたが、JUnit5では@BeforeEachに変わりました。
JUnit5は、JUnit Platform・JUnit Jupiter・JUnit Vintageの3つのモジュールに分かれました。
テストを動かす土台(Platform)と書き方(Jupiter)が分離されたため、拡張しやすくなっています。
JUnit6は2025年9月30日に正式リリース(GA)されました。以降の修正版は公式のリリースノートで確認できます。
一方のJUnit5も、2026年4月に5.14.4が出るなど保守リリースが続いています。
ただし、Java17以上が必須になったことや既存プロジェクトの移行コストから、実務では引き続きJUnit5(Jupiter)が広く使われています。
これから初めてJavaのテストを学ぶなら、まずはJUnit5から始めるのが現実的です。
JUnit4とJUnit5の主な違いを表にまとめました。
JUnit4からJUnit5への移行手順
既存プロジェクトでJUnit4からJUnit5に移行する場合、以下の手順で進めます。
- 依存関係の変更:
pom.xml/build.gradleからjunit:junitを削除し、junit-jupiter-api・junit-jupiter-engineに置き換えます。 - 段階的な移行:
junit-vintage-engineを依存関係に追加すれば、既存のJUnit4形式のテストを残したまま、新規テストだけJUnit5で書けます。テストを一度に全て書き直す必要はありません。 - アノテーション名の一括置換:
@Before→@BeforeEach、@BeforeClass→@BeforeAllなど、上記の比較表に沿ってIDEの一括置換機能で変更します。 - ランナーの置き換え: Spring Bootプロジェクトなどで
@RunWith(SpringRunner.class)を使っている場合は置き換えが必要です。JUnit5では@RunWith自体が廃止されたため、@ExtendWith(SpringExtension.class)を使います。
JUnit5の導入方法(Maven/Gradle)
JUnitをプロジェクトに導入するのは簡単です。
特に、MavenやGradleといったビルドツールを利用すると、数行の設定を追加するだけで済みます。
Maven/Gradleによる導入
Mavenの場合 (pom.xml)
pom.xmlファイルの<dependencies>セクションに、以下の依存関係を追加します。
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.14.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.14.4</version>
<scope>test</scope>
</dependency>
<scope>test</scope>は、このライブラリがテストコードのコンパイルと実行時にのみ必要であることを示します。
JUnit5はJava 8以上で動作します。
Gradleの場合 (build.gradle)
build.gradleファイルに以下を記述します。Gradle 9以降は junit-platform-launcher を宣言しないとテストが起動しないため、この行も忘れずに入れてください。
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.14.4'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.14.4'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.14.4'
}
test {
useJUnitPlatform()
}
IDE(IntelliJ/Eclipse)でのセットアップ
IntelliJ IDEA・Eclipse・VS Code(Extension Pack for Java)などのIDEを使っている場合、さらに簡単です。
たとえばIntelliJ IDEAでGradleプロジェクトを新規作成すると、通常はJUnitの依存関係が最初から入っています(Mavenプロジェクトや入っていない場合は上記の依存関係を追加します)。
テストクラスを手動で作る場合も、IDEがJUnitの追加を提案してくれます。
JUnit5の基本的なテストの書き方
ここでは、計算を行うシンプルなCalculatorクラスを例に、基本的なテストの書き方を解説します。
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
@Testアノテーションの使い方
JUnit5では、テスト用に書いたメソッドに@Testアノテーションを付けると、JUnitがそのメソッドをテストケースとして実行します。
テストクラスは、慣習としてsrc/test/javaディレクトリ配下に作成します。
import org.junit.jupiter.api.Test;
class CalculatorTest {
@Test
void testAdd() {
// ここにテストのロジックを記述する
}
}
アサーション(assertEquals / assertTrueなど)
テストコードの核心は「アサーション(Assertion)」、つまりメソッドの実行結果が期待どおりかを検証する仕組みです。
JUnit5ではAssertionsクラスのstaticメソッドを使います。
最もよく使われるのが、2つの値が等しいかを確認するassertEqualsです。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void 足し算が正しくできるか検証する() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result, "2 + 3 は 5 になるべきです");
}
}
assertEqualsは、第1引数に「期待値」、第2引数に「実際の値」を取ります。
第3引数は、テストが失敗したときに表示されるメッセージで、省略できます。
他にも、以下のような便利なアサーションメソッドがあります。
アサーションメソッド
assertTrue(boolean condition): 条件がtrueであることを検証assertFalse(boolean condition): 条件がfalseであることを検証assertNotNull(Object obj): オブジェクトがnullでないことを検証assertNull(Object obj): オブジェクトがnullであることを検証
assertAllやassertIterableEqualsを含む全メソッドの使い分けは、JUnitのassertメソッド一覧(早見表)にまとめています。
例外の検証
特定の条件下で、メソッドが正しく例外をスローするかを検証したいケースもあります。
JUnit5では、assertThrowsメソッドを使って簡単に例外テストを記述できます。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SomeServiceTest {
@Test
void 引数がnullの場合に例外をスローするか() {
SomeService service = new SomeService();
// service.process(null) を実行した際に IllegalArgumentException がスローされることを期待する
assertThrows(IllegalArgumentException.class, () -> {
service.process(null);
});
}
}
assertThrowsの第1引数には期待する例外の型、第2引数には例外が出るはずの処理をラムダ式で渡します。
意図した例外が正しく発生するかを安全にテストできます。
テストの実行方法(Maven/Gradle/IDE)
テストは書いただけでは動きません。ビルドツールのコマンドかIDEから実行して、はじめて結果がわかります。
コマンドラインで実行する場合は、プロジェクトのルートディレクトリで次のように入力します。
# Maven:すべてのテストを実行
mvn test
# Maven:CalculatorTestだけを実行
mvn test -Dtest=CalculatorTest
# Gradle:すべてのテストを実行
./gradlew test
# Gradle:CalculatorTestだけを実行
./gradlew test --tests CalculatorTest
Mavenで実行すると、最後に次のような集計行が表示されます。
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
FailuresとErrorsが0なら全テスト成功です。Failuresはアサーションの不一致、Errorsは想定外の例外、Skippedは@Disabledなどで飛ばしたテストの件数を表します。
「Tests run: 0」と表示されてテストが見つからない場合は、MavenのSurefireプラグインが古い可能性があります。JUnit5のテストを実行するには、maven-surefire-pluginを2.22.0以上(できれば3系)に上げてください。
IDEから実行する場合、IntelliJ IDEAはテストクラスやメソッドの横にある実行ボタン(▶)をクリックします。Eclipseはテストクラスを右クリックし、[実行]→[JUnitテスト]を選びます。
どちらも結果は緑(成功)・赤(失敗)で一覧表示されます。
テストケースの構造と設計
読みやすく保守しやすいテストを書くには、構造と命名が大切です。3つのポイントを紹介します。
Arrange-Act-Assertパターンとは
テストコードはArrange-Act-Assert (AAA) パターンで書くのが効果的です。 テストの目的が明確になり、誰が見てもわかりやすくなります。
AAAパターン
- Arrange(準備): テスト対象のオブジェクトを生成し、必要なデータや状態を準備するフェーズ。
- Act(実行): テスト対象のメソッドを実行し、結果を受け取るフェーズ。
- Assert(検証): 実行結果が期待通りであるかをアサーションメソッドで検証するフェーズ。
実務でよくある失敗は、1つのテストメソッドに複数のActとAssertを詰め込むことです。テストが失敗したとき、どのActが原因かわからなくなります。
1テスト1検証を心がけましょう。
@Test
void 足し算が正しくできるか検証する_AAAパターン() {
// Arrange
Calculator calculator = new Calculator();
int a = 10;
int b = 20;
int expected = 30;
// Act
int actual = calculator.add(a, b);
// Assert
assertEquals(expected, actual);
}
テストクラスとテストメソッドの命名規則
テストメソッドの命名で理想的なのは、名前を読むだけで「何を」「どの状況で」「どう検証しているか」がわかることです。
- テストクラス名:
[テスト対象クラス名]Testとするのが一般的です。(例:CalculatorTest) - テストメソッド名: 英語なら
should[期待する結果]When[条件]のような形式があります。日本語なら「〇〇の場合は〇〇を返すこと」のように自然な文章で書くとわかりやすいです。
良い命名は、テストが失敗したときのエラーメッセージを読むだけで、問題の原因を推測する手助けとなります。
筆者のチームでは、日本語メソッド名を採用しています。IDEのテスト結果が一目で読めるため、コードレビューの効率が上がりました。
英語名か日本語名かはチームで統一することが大切です。
ユニットテスト(単体テスト)と統合テストの違い
JUnitが得意とする「ユニットテスト(単体テスト)」は、クラスやメソッドなど1つの部品を対象にします。
データベースやAPIなど外部への依存を切り離し、対象のロジックだけを検証します。
一方、「統合テスト」は複数のコンポーネントを組み合わせ、連携が正しく動くかを確認します。
ControllerからServiceを経由してDBにアクセスする一連の流れが典型例です。
ただし、ユニットテストだけでは検知できない不具合もある。
典型例が、同一クラス内のメソッド呼び出しでは@Transactionalが効かない(プロキシの限界)という問題だ。
各メソッド単体のユニットテストはすべて通るのに、サービス層を経由して呼び出す統合的な流れの中でだけ不具合が現れる。
トランザクションをまたぐ処理は、ユニットテストに加えて統合テストでも確かめておく。
テストが失敗したら、どう確認する?
テストを書き始めたばかりの頃は、テストが失敗した理由を読み解くこと自体でつまずきがちです。ここでは失敗時の確認手順を整理します。
アサーションエラーの読み方
assertEqualsが失敗すると、次のようなメッセージが表示されます。
org.opentest4j.AssertionFailedError: 2 + 3 は 5 になるべきです ==> expected: <5> but was: <6>
expected(期待値)とwas(実際の値)を見比べれば、どこがズレているかが一目でわかります。
assertEqualsの第3引数に渡したメッセージ(例:「2 + 3 は 5 になるべきです」)は、エラーの先頭に表示されます。
アサーションが複数あるテストほど、第3引数のメッセージを具体的に書いておくと原因を早く特定できます。
よくある失敗原因3パターン
失敗原因
- @BeforeAllと@BeforeEachの取り違え: テストごとにリセットすべきオブジェクトを
@BeforeAll(クラス全体で1回だけ実行)で初期化してしまう。その結果、前のテストで変更された状態が次のテストに残る。 - テスト間での状態共有: 同じテストクラス内でstaticフィールドやモックの状態を複数のテストで使い回し、実行順序によって結果が変わる。
- 非同期処理のタイミングのズレ: 非同期処理の完了を待たずにアサーションを実行してしまい、処理が終わる前に検証してテストが不安定になる(いわゆるFlakyテスト)。
IntelliJ IDEAやEclipseでは、テスト結果画面で失敗したテストをクリックすると、該当するアサーション行にジャンプできます。
まずはエラーメッセージのexpectedとwasを見比べ、次に上記3パターンに該当していないかを確認する、という順番で切り分けると効率的です。
JUnit5の便利なアノテーション
基本をマスターしたら、テストをさらに効率化するアノテーションを使いましょう。
@BeforeEach / @AfterEach(初期化と後処理)
@BeforeEachは、各テストの前に共通の初期化処理を実行するアノテーションです。複数のテストで同じオブジェクト生成が必要なときに役立ちます。
同様に、@AfterEachは各テストメソッドの実行後に呼ばれ、リソースの解放などの後処理に使います。
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
// 各テストの前にCalculatorインスタンスを生成する
this.calculator = new Calculator();
System.out.println("テスト準備完了");
}
@AfterEach
void tearDown() {
// 各テストの後に実行される
System.out.println("テスト後処理完了");
}
@Test
void testAdd() {
assertEquals(5, calculator.add(2, 3));
}
@Test
void testSubtract() {
// assertEquals(1, calculator.subtract(3, 2));
}
}
クラス全体で1回だけ実行したい処理には、@BeforeAllと@AfterAllを使います。DB接続の確立のような重い準備が典型例で、メソッドは原則staticにする必要があります。
4つのアノテーションが呼ばれる順番を図にすると、次のようになります。
setUp()calculatorを生成。「テスト準備完了」と出力testAdd)tearDown()後処理。「テスト後処理完了」と出力setUp()calculatorをもう一度生成。「テスト準備完了」と出力testSubtract)tearDown()後処理。「テスト後処理完了」と出力JUnit5は標準ではテストメソッドごとにテストクラスのインスタンスを新しく作ります。そのため@BeforeEachで初期化したフィールドは、テスト間で状態が引き継がれません。
@ParameterizedTestによるパラメータ化テスト
同じロジックのテストを、異なる入力値と期待値で何度も実行したいケースは多い。
@ParameterizedTestを使うと、テストコードの重複を避けられます。
@ValueSourceを使えば、簡単な値のリストをパラメータとして渡せます。
なお、@ParameterizedTestや@ValueSourceはjunit-jupiter-paramsに含まれます。導入方法の節で示したjunit-jupiter-apiとjunit-jupiter-engineだけでは入らないため、org.junit.jupiter:junit-jupiter-params(バージョンは同じ5.14.4)もtestスコープで追加してください。
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
class StringUtilsTest {
@ParameterizedTest
@ValueSource(strings = {"", " ", "\t"})
void 文字列がブランクであるか検証する(String input) {
assertTrue(input.isBlank());
}
}
注意
この例で使ったString#isBlank()はJava 11以降のメソッドです。
Java 8環境ではinput.trim().isEmpty()に置き換えてください。
さらに、@CsvSourceを使えば、カンマ区切りの値で複数の引数(入力値と期待値など)を渡せます。
@DisplayNameでテスト名をわかりやすくする
JUnit5の@DisplayNameアノテーションを使うと、テスト結果のレポートに任意の名前を表示できます。
メソッド名が英語でも、レポートには日本語の説明を出せるので便利です。
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DisplayName("Calculatorクラスのテスト")
class CalculatorTest {
@Test
@DisplayName("2 + 3 = 5 になること")
void testAdd() {
Calculator calculator = new Calculator();
assertEquals(5, calculator.add(2, 3));
}
}
テストメソッド名を日本語にする方法もありますが、@DisplayNameを使えばメソッド名は英語の命名規則に従いつつ、レポートだけ日本語にできます。
チーム開発ではこちらが推奨されるケースが多いです。
@Nestedによる階層的テスト構造
テスト対象クラスの機能が複雑になると、テストクラスも肥大化しがちです。
@Nestedアノテーションを使い、内部クラスでテストをグループ化すると、テストの構造がわかりやすくなります。
class BankAccountTest {
// 口座の初期状態に関するテスト
@Nested
class 初期状態のテスト {
@Test
void 新規口座の残高は0円であること() {
// ...
}
}
// 入金機能に関するテスト
@Nested
class 入金テスト {
@Test
void 正の金額を入金すると残高が増えること() {
// ...
}
@Test
void 負の金額を入金しようとすると例外が発生すること() {
// ...
}
}
}
関連するテストをまとめると、テスト結果もグループ単位で表示されるため、どの機能のテストが落ちたかをすぐ追えます。
@Disabledでテストを一時的に無効化する
未実装の機能に対応するテストや、環境依存で一時的に実行できないテストは、削除せずに@Disabledで無効化しておくと、後で対応漏れを防げます。
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class CalculatorTest {
@Test
@Disabled("未実装のため一時的に無効化(担当: Taro, 対応予定: 次スプリント)")
void 割り算の結果が正しいこと() {
// ...
}
}
@Disabledは前述の比較表にあるJUnit4の@Ignoreに対応するアノテーションです。
引数に無効化した理由を残しておくと、後でテストを見た人(未来の自分を含む)が状況を把握しやすくなります。
Mockitoを使ったモックテスト
実際の開発では、クラスが他のクラスや外部システム(データベース、APIなど)に依存していることがほとんどです。
依存先まで含めるとユニットテストの範囲を超えてしまいます。
そこで登場するのが「モック(Mock)」です。モックとは、本物のオブジェクトのふりをする偽物のオブジェクトのこと。
Mockitoなどのモックライブラリを使うと、モックを簡単に作成できます。
Mockitoの基本と導入方法
Mockitoは、Javaで最も人気のあるモックライブラリの一つです。
Mockitoを使うことで、依存オブジェクトの振る舞いを自由に定義し、テスト対象のロジックだけに集中できます。
導入はJUnitと同様に、ビルドツールに依存関係を追加するだけです。なお、Mockito 5系はJava 11以上が必要です(Java 8環境ではMockito 4系を使います)。
Mavenの場合 (pom.xml)
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.23.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.23.0</version>
<scope>test</scope>
</dependency>
依存オブジェクトはどうモック化する?
例えば、ユーザー情報をUserRepositoryから取得して処理を行うUserServiceをテストしたいとします。
// テスト対象クラス
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
public String getUserName(int id) {
User user = repository.findById(id);
if (user != null) {
return user.getName();
}
return "Unknown";
}
}
UserRepositoryはデータベースにアクセスするため、ユニットテストではモックに置き換えます。
Mockitoを使えば、次のようにテストを書けます。
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.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) // Mockito拡張を有効にする
class UserServiceTest {
@Mock // UserRepositoryのモックを作成
private UserRepository mockRepository;
@InjectMocks // モックを注入してUserServiceのインスタンスを生成
private UserService userService;
@Test
void 存在するユーザーIDの場合はユーザー名を返すこと() {
// Arrange: モックの振る舞いを定義
User user = new User(1, "Taro");
// repository.findById(1)が呼ばれたら、作成したuserオブジェクトを返すように設定
when(mockRepository.findById(1)).thenReturn(user);
// Act: テスト対象メソッドを実行
String userName = userService.getUserName(1);
// Assert: 結果を検証
assertEquals("Taro", userName);
// Verify: repository.findById(1)が1回だけ呼ばれたことを検証
verify(mockRepository, times(1)).findById(1);
}
}
when(mockRepository.findById(1)).thenReturn(user);「findById(1)が呼ばれたら user(Taro)を返す」とモックに登録する(スタブ)userService.getUserName(1);テスト対象のメソッドを呼ぶ。@InjectMocksでモックが注入済みrepository.findById(1);UserServiceは本物のリポジトリだと思ってモックを呼ぶ。DBには行かないreturn user; // Taroモックは登録どおりの user を返すだけassertEquals("Taro", userName);UserServiceが "Taro" を返し、期待値と一致するので成功verify(mockRepository, times(1)).findById(1);モックに残った呼び出し記録が1回なので、こちらも成功when(...).thenReturn(...)は、モックの振る舞い(スタブ:あらかじめ決めた値を返す設定)を定義するメソッドです。
verify(...)では、モックのメソッドが期待通りに呼ばれたかを検証します。
モックを使うことで、データベースに接続せずにUserServiceのロジックをテストできました。
モックを使うかどうかの判断基準はシンプルです。
テスト対象のロジックに集中したいとき、外部依存(DB・API・ファイルシステム)を切り離すためにモックを使います。
逆に、値の変換や計算だけを行うユーティリティクラスには、モックは不要です。
もう一つの判断軸として、「モックの数が増えすぎていないか」も見ておきたい。
1つのテストのために何個も@Mockを用意しなければならないなら、問題はテストの書きにくさだけではない。
テスト対象クラスが多くのクラスに依存しすぎている、という設計上のサインであることが多い。
モックが増えて辛くなったら、まずクラス設計を疑ってみる価値がある。
ここで紹介したのはMockitoの導入部分のみだ。spy・doReturn・ArgumentCaptorによる引数検証や静的メソッドのモック化は扱っていない。
Spring Bootの@MockitoBeanへの移行まで含めた内容は、Mockitoの使い方を解説した別記事で扱っている。
よくある質問
Q1. JUnit5とJUnit4の違いは何ですか?
A1. 最大の違いはアーキテクチャとアノテーション名です。JUnit4は単一jarでしたが、JUnit5はPlatform・Jupiter・Vintageの3モジュール構成になりました。初期化処理も@Before(JUnit4)から@BeforeEach(JUnit5)に変わっています。
Q2. JUnit5はどうやって導入しますか?
A2. MavenまたはGradleの依存関係にjunit-jupiter-apiとjunit-jupiter-engineを追加します(Gradleではjunit-platform-launcherも追加)。IntelliJ IDEAでGradleプロジェクトを新規作成した場合は、通常JUnitの依存関係が最初から入っています。
Q3. JUnit5でモックを使うにはどうすればいいですか?
A3. Mockitoライブラリを使います。@ExtendWith(MockitoExtension.class)でMockito拡張を有効にし、@Mockでモックを作成、@InjectMocksでテスト対象に注入します。外部依存(DB・APIなど)を切り離したいときに使います。
Q4. パラメータ化テストとは何ですか?
A4. 同じロジックを異なる入力値・期待値で繰り返しテストする仕組みです。JUnit5では@ParameterizedTestと@ValueSourceや@CsvSourceを組み合わせて使うと、テストコードの重複を避けられます。
Q5. @DisplayNameは何のために使いますか?
A5. テスト結果のレポートに任意の名前を表示するためのアノテーションです。メソッド名は英語の命名規則に従いつつ、レポートだけ日本語の説明にできるため、チーム開発で推奨されるケースが多いです。
Q6. テストを一時的にスキップするにはどうすればいいですか?
A6. @Disabledアノテーションを使います。JUnit4の@Ignoreに対応するもので、引数に無効化した理由を残しておけば、未実装機能や環境依存のテストを削除せずに一時停止できます。
Q7. JUnit6が出た今でもJUnit5を学ぶべきですか?
A7. はい、現実的な選択です。JUnit6は2025年9月30日に正式リリースされましたが、Java17以上が必須になったことや既存プロジェクトの移行コストから、2026年時点でも実務ではJUnit5(Jupiter)が広く使われています。
Q8. ユニットテストと統合テストの違いは何ですか?
A8. ユニットテストはクラスやメソッドなど1つの部品を対象に、外部依存を切り離してロジックだけを検証します。統合テストは複数のコンポーネントを組み合わせ、連携が正しく動くかを確認します。両方を書くことで、単体では見えない不具合も検知できます。
まとめ
JUnitによるユニットテストは、Javaエンジニアの必須スキルです。使い方の流れは、冒頭で示した3ステップに集約されます。依存関係を追加し、@Testとアサーションでテストを書き、mvn testやIDEで実行して結果を確認する。まずは手元のクラス1つで、この流れを一周させてみてください。
最初はテストコードに時間がかかります。
それでも、テストに使った時間は、修正のたびに手動確認を繰り返す手間の削減と、デグレードの早期発見という形で返ってきます。
JUnit5の基本を理解したら、次はSpring Boot 4での統合テスト(@SpringBootTest)や、カバレッジ計測ツール(JaCoCo)に挑戦してみてください。
| REV. | DATE | 内容 |
|---|---|---|
| 6 | 2026-10-21 | 一部の体験談を一般的な説明に改め、同じ説明の繰り返しを減らした |
| 5 | 2026-10-15 | 図解を描き直し(図面のデザインにそろえた) |
| 4 | 2026-10-14 | 一人称と言い回しの表記をそろえた |
| 3 | 2026-08-21 | 2026年8月時点の情報で全体を見直し(古い記述を6件更新) |
| … ほか1回の改訂 | ||
| 1 | 2025-07-30 | 初版 |






