本文へスキップ
T2R tech2rich.com
プログラミング 📚 Java入門 第13回 #Java #入門 #プログラミング初心者 #JUnit #テスト #テスト駆動開発

【Java入門 第13回】JUnit でテストを書く|単体テストの基本を完全マスター

Javaの単体テストフレームワーク JUnit を完全初心者向けに徹底解説。@Test・assertEquals・@BeforeEach の使い方、テストケース設計のコツまで丁寧に解説します。

📅 公開: 2026.05.26 🔄 更新: 2026.05.26 ⏱ 読了 約9分 ✍ 管理人

第12回 でマルチスレッドを学びました。今回は実務で必須の 「単体テスト(JUnit)」 を学びます。

「プログラムを書いて、自分で実行して、目で確認して…」これでは人間が見落とす可能性があります。 JUnit(ジェイユニット) は、自動でテストしてくれる仕組み。書いたコードが正しいかを マシンが代わりにチェックしてくれる、現代の Java 開発では欠かせない道具です。

先輩

この記事のゴール

「JUnit でテストを書く・実行する」「@Test と assertEquals の使い方」「テスト前後の準備・後片付け(@BeforeEach / @AfterEach)」「よいテストの書き方」が理解できることです。

なぜテストを書くのか?

JUnit を学ぶ前に、テストの意義をひと言で理解しましょう。

💡 テストとは: 「このコードはちゃんと動くはず」を コードで証明する こと。

テストがあると何が嬉しい?

  1. バグの早期発見: 修正したつもりが別の場所を壊しても、すぐ気づける
  2. 安心してリファクタリング: 既存テストが通れば動作は保たれている
  3. 仕様書としても機能: 「このメソッドはこういう挙動」がテストコードで明確化
  4. ドキュメント不要: 入出力例がコードに残るので、新人が読むだけで理解できる

準備: プロジェクトに JUnit を入れる

JUnit は標準ライブラリではなく 外部ライブラリなので、プロジェクトに追加が必要です。

Maven の場合(pom.xml)

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>

Gradle の場合(build.gradle)

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

test {
    useJUnitPlatform()
}

💡 IntelliJ IDEA なら、新規プロジェクト作成時に 「Add Sample Code」+「JUnit 5」 を選べば自動セットアップ完了。本記事では JUnit 5(Jupiter) を前提に解説します。

テスト対象のクラスを用意

まず、テストする対象の Calculator クラス を作ります。

// src/main/java/Calculator.java
public class Calculator {

    // 足し算するメソッド
    public int add(int a, int b) {
        return a + b;
    }

    // 引き算するメソッド
    public int subtract(int a, int b) {
        return a - b;
    }

    // 割り算するメソッド(0 除算で例外)
    public int divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("0 で割ることはできません");
        }
        return a / b;
    }
}

はじめての JUnit テスト

// src/test/java/CalculatorTest.java
import org.junit.jupiter.api.Test;            // @Test を使うため
import static org.junit.jupiter.api.Assertions.*;  // assertEquals 等を使うため

public class CalculatorTest {

    // @Test を付けたメソッドが「1 つのテストケース」になる
    @Test
    public void add_2_plus_3_equals_5() {
        // ── ① 準備(Arrange):テスト対象を用意 ──
        Calculator calc = new Calculator();

        // ── ② 実行(Act):対象メソッドを呼ぶ ──
        int result = calc.add(2, 3);

        // ── ③ 検証(Assert):期待通りかチェック ──
        assertEquals(5, result);   // 「期待値=5, 実際の値=result」
    }
}

コード解説

部分意味
@Testこのメソッドはテストケース、と JUnit に伝える目印(アノテーション)
import static ...Assertions.*assertEquals などを Assertions.assertEquals と書かずに済ませる
assertEquals(期待値, 実際の値)2 つが等しければテスト成功、違えば失敗

実行方法

緑のチェックマーク ✓ が出れば成功、赤の × が出れば失敗です。

AAA パターン(Arrange-Act-Assert)

良いテストの王道は AAA パターン:

  1. Arrange(準備): テスト対象とデータを用意
  2. Act(実行): テスト対象を実行
  3. Assert(検証): 期待通りか確認

このパターンを意識して書くだけで、読みやすいテストになります。

よく使う assert メソッド

メソッド説明
assertEquals(期待, 実際)2 つが等しいかassertEquals(5, result)
assertNotEquals(期待しない, 実際)等しくないかassertNotEquals(0, result)
assertTrue(条件)条件が true かassertTrue(name.startsWith("佐"))
assertFalse(条件)条件が false かassertFalse(list.isEmpty())
assertNull(値)null かassertNull(user.getEmail())
assertNotNull(値)null でないかassertNotNull(result)
assertThrows(クラス, 実行)例外が投げられるか(下記参照)

例外を確認: assertThrows

@Test
public void divide_by_zero_throws_exception() {
    Calculator calc = new Calculator();

    // 「ラムダ式の中身を実行したら、IllegalArgumentException が出るはず」
    assertThrows(IllegalArgumentException.class, () -> {
        calc.divide(10, 0);   // ここで例外が出るはず
    });
}

ポイント: () -> { ... } で実行する処理を渡し、その中で 指定した例外が起きるかを検証。例外が起きないと テスト失敗になります。

複数テストケースをまとめる

1 つのテストクラスに 複数の @Test メソッド を書けます。

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CalculatorTest {

    @Test
    public void add_positive_numbers() {
        Calculator calc = new Calculator();
        assertEquals(5, calc.add(2, 3));
    }

    @Test
    public void add_negative_numbers() {
        Calculator calc = new Calculator();
        assertEquals(-1, calc.add(-3, 2));
    }

    @Test
    public void subtract_works() {
        Calculator calc = new Calculator();
        assertEquals(10, calc.subtract(15, 5));
    }

    @Test
    public void divide_works() {
        Calculator calc = new Calculator();
        assertEquals(3, calc.divide(10, 3));   // 10/3 は整数除算で 3
    }

    @Test
    public void divide_by_zero_throws() {
        Calculator calc = new Calculator();
        assertThrows(IllegalArgumentException.class, () -> calc.divide(10, 0));
    }
}

@BeforeEach で重複を減らす

「毎回 new Calculator() を書くのが面倒…」── そこで @BeforeEach を使います。

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CalculatorTest {

    private Calculator calc;   // フィールドにしておく

    // 各 @Test メソッドが実行される「前に」毎回呼ばれる
    @BeforeEach
    public void setUp() {
        calc = new Calculator();   // 各テストごとにフレッシュなインスタンスを用意
    }

    @Test
    public void add() {
        assertEquals(5, calc.add(2, 3));   // 「calc =」を書かなくて済む!
    }

    @Test
    public void subtract() {
        assertEquals(10, calc.subtract(15, 5));
    }
}
アノテーション実行タイミング
@BeforeEach各テストの前に毎回実行(初期化用)
@AfterEach各テストの後に毎回実行(後片付け)
@BeforeAll全テスト開始前に 1 回だけ実行(static メソッド)
@AfterAll全テスト終了後に 1 回だけ実行(static メソッド)

@DisplayName で読みやすく

テストメソッド名は長くなりがち。@DisplayName日本語の説明を付けられます。

@Test
@DisplayName("正の数同士の足し算が正しく動く")
public void add_positive() {
    assertEquals(5, calc.add(2, 3));
}

@Test
@DisplayName("0 で割ると IllegalArgumentException が投げられる")
public void divide_by_zero() {
    assertThrows(IllegalArgumentException.class, () -> calc.divide(10, 0));
}

テスト結果一覧に 日本語で結果が並ぶので、レポートとしても読みやすくなります。

よいテストを書く 5 つのコツ

編集部より

編集部の鉄則

テストは 「壊れたら直すべきコードが分かる」 ためのもの。最初は「正しく動く」と「例外が出る」の 2 ケースだけでも価値があります。完璧を目指さず、まずは 書く習慣を!

① 1 テスト 1 検証(1 アサーション原則)

// ❌ 何のテストか分からない
@Test
public void test() {
    assertEquals(5, calc.add(2, 3));
    assertEquals(10, calc.subtract(15, 5));
    assertEquals(3, calc.divide(10, 3));
}

// ⭕ それぞれ分けて、何のテストか名前で分かるように
@Test public void add_returns_sum() { ... }
@Test public void subtract_returns_difference() { ... }
@Test public void divide_returns_quotient() { ... }

② 「正常系」と「異常系」を両方書く

③ テスト名で「何を検証しているか」を語る

@Test
public void divide_by_zero_throws_IllegalArgumentException() { ... }
// ↑ メソッド名を読むだけで内容が分かる

④ テスト同士は独立に

@BeforeEach で初期化しておけば、他のテストの影響を受けません。テスト順序に依存させない!

⑤ 失敗時のメッセージを書くと親切

assertEquals(5, calc.add(2, 3), "正の数の足し算が誤っている");
// ↑ 失敗時に「正の数の足し算が誤っている」と表示される

練習問題

以下の StringUtil クラスのテストを書いてみましょう。

テスト対象

public class StringUtil {

    // 文字列を反転する(例: "hello" → "olleh")
    public String reverse(String s) {
        if (s == null) {
            throw new IllegalArgumentException("null は渡せません");
        }
        return new StringBuilder(s).reverse().toString();
    }

    // 文字列が回文(reverse しても同じ)かチェック
    public boolean isPalindrome(String s) {
        if (s == null) return false;
        return s.equals(reverse(s));
    }
}

解答例

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class StringUtilTest {

    private StringUtil util;

    @BeforeEach
    public void setUp() {
        util = new StringUtil();
    }

    // ── reverse のテスト ──

    @Test
    @DisplayName("通常文字列の反転が正しく動く")
    public void reverse_normal_string() {
        assertEquals("olleh", util.reverse("hello"));
    }

    @Test
    @DisplayName("空文字を反転しても空文字を返す")
    public void reverse_empty_string() {
        assertEquals("", util.reverse(""));
    }

    @Test
    @DisplayName("null を渡すと IllegalArgumentException が出る")
    public void reverse_null_throws_exception() {
        assertThrows(IllegalArgumentException.class, () -> util.reverse(null));
    }

    // ── isPalindrome のテスト ──

    @Test
    @DisplayName("回文を渡すと true を返す")
    public void isPalindrome_true() {
        assertTrue(util.isPalindrome("level"));    // level → reverse でも level
    }

    @Test
    @DisplayName("回文でない文字列で false を返す")
    public void isPalindrome_false() {
        assertFalse(util.isPalindrome("hello"));
    }

    @Test
    @DisplayName("null を渡すと false を返す")
    public void isPalindrome_null_returns_false() {
        assertFalse(util.isPalindrome(null));
    }
}

まとめ

第 13 回では、以下を学びました。

次回はいよいよ 最終回! 「Java フレームワーク(Spring Boot 入門)」 を学びます。 現代の Java 開発の主役 である Spring Boot で、Web API を作る基本を学びましょう。お楽しみに!

関連の技術記事