JUnit:その概要、主要概念、動作方法

著者: IT Sectr 公開日: 2026-04-08 読了時間: 8 分

JUnitは、JavaおよびKotlinエコシステムにおける単体テストの標準フレームワークであり、Android開発において独立したコンポーネントレベルでビジネスロジックを検証するために使用されます。このフレームワークは、アノテーション、アサーションメソッド、Test Runnerのセットを提供し、テストの自動検出と実行を行います。JUnit.orgによると、このライブラリはJVMエコシステムにおける単体テストの最も人気のあるソリューションであり続けており、70%以上のJavaプロジェクトが何らかのバージョンのJUnitを使用しています。

主要ポイント

  • JUnit — JavaおよびKotlinコードの単体テストのためのオープンソースフレームワークです。
  • アノテーション — @Test、@BeforeEach、@BeforeAllがテストクラスのライフサイクルを管理します。
  • アサーション — assertEquals、assertTrue、assertThrowsが期待される実行結果を検証します。
  • パラメータ化テスト — 1つのテストを異なる入力データセットで実行できます。
  • Test Runner — JUnitのインフラストラクチャがプロジェクト内のすべてのテストを自動的に検出して実行します。

JUnitとは?

JUnitは、JavaおよびKotlinで反復可能な単体テストを作成および実行するためのオープンソースフレームワークです。これはxUnitエコシステムの一部であり、Kent BeckとErich Gammaのアーキテクチャに基づくフレームワークファミリーで、Android StudioおよびIntelliJ IDEAの標準テストツールです。

JUnitの主な役割は、コードの小さな断片(メソッド、クラス)を分離し、制御された条件下でその動作を検証することです。テストはアノテーション付きの通常のJava/Kotlinクラスとして記述され、フレームワークがテストの検出、ライフサイクル管理、実行統計の収集を処理します。

JUnitの最初のバージョンは1997年に登場し、テスト駆動開発(TDD)のプラクティスを普及させることで開発アプローチを根本的に変えました。現在、JUnit 5(Jupiter)が最新バージョンであり、Java 8+と拡張機能をサポートするモジュラーアーキテクチャで完全に再設計されています。

JUnitの仕組み

JUnitの実行メカニズムはTest Runnerパターンに基づいており、classpathをスキャンし、@Testアノテーションが付いたメソッドを見つけ、テストクラスのインスタンスを作成し、特定の順序でメソッドを実行します。Test Runnerはライフサイクルを管理します:BeforeAll → BeforeEach → Test → AfterEach → AfterAll。

テストクラスのライフサイクル

JUnitは各テストメソッドを個別のクラスインスタンスにラップし、テスト間の分離を保証します。つまり、クラスのフィールドは異なる@Testメソッド間で状態を保持せず、各テストはクリーンなオブジェクトから開始されます。

基本的なテスト構造

JUnitの最も単純なテストは、@Testアノテーションが付いたメソッドで、テスト対象のコードを呼び出し、アサーションを使用して結果を検証します。アサーションが失敗した場合、テストは失敗と見なされ、JUnitがエラーを報告します。

java
@Test
void additionShouldReturnCorrectSum() {
    var calculator = new Calculator();
    var result = calculator.add(2, 3);
    assertEquals(5, result);
}

Test Runnerは自動的にそのようなメソッドを見つけ、実行し、結果を報告します。メソッドが例外をスローしなければテストは成功(green)、アサーションが失敗するとテストは失敗(red)します。

JUnitアノテーション:テストライフサイクル

JUnitのアノテーションは、テストコードをいつどのように実行するかを定義します。JUnit 5では、アノテーションはorg.junit.jupiter.apiパッケージにあり、データ準備、テスト実行、リソースクリーンアップのすべての段階をカバーしています。

アノテーション目的実行タイミング
@Testテストメソッドをマーク呼び出しごとに1回
@BeforeEach各テスト前のセットアップ各@Testの前
@BeforeAllクラスの1回限りの初期化全テストの前に1回
@AfterEach各テスト後のクリーンアップ各@Testの後
@AfterAllクラスの1回限りの終了処理全テストの後に1回
@DisplayName人間が読めるテスト名装飾

アノテーション使用例

適切なライフサイクルを持つ完全なテストクラスを考えてみましょう。setUpメソッドは各テストの前に新しいCalculatorインスタンスを作成し、tearDownはリソースを解放します(例:ファイル記述子やデータベース接続のクローズ)。

java
class CalculatorTest {

    private Calculator calculator;

    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }

    @Test
    void subtractionShouldReturnCorrectResult() {
        int result = calculator.subtract(10, 4);
        assertEquals(6, result);
    }

    @AfterEach
    void tearDown() {
        calculator.reset();
    }
}

アサーション:JUnitでの結果検証

アサーションは、実際の結果を期待される結果と比較し、一致しない場合に例外をスローする静的メソッドです。JUnit 5はorg.junit.jupiter.api.Assertionsクラスを提供し、単純な値の比較からタイムアウトチェックやグループ化されたアサーションまで、さまざまな検証シナリオのための25以上のメソッドがあります。

  • assertEquals(expected, actual) — equals()で等価性を検証します。
  • assertTrue(condition) — 条件が真であることを検証します。
  • assertFalse(condition) — 条件が偽であることを検証します。
  • assertNotNull(object) — オブジェクトがnullでないことを検証します。
  • assertNull(object) — オブジェクトがnullであることを検証します。
  • assertThrows(exception, executable) — コードが指定された例外をスローすることを検証します。
  • assertAll(executables) — 複数のアサーションをグループ化し、最初の失敗で止まらずにすべて実行します。

例外テストのためのassertThrows

assertThrowsメソッドは特に注目に値します。コードがゼロ除算、nullの受け渡し、制限超過などのエラー状況を正しく処理するかどうかを検証できます。

java
@Test
void divisionByZeroShouldThrowException() {
    Calculator calc = new Calculator();

    ArithmeticException exception = assertThrows(
        ArithmeticException.class,
        () -> calc.divide(10, 0)
    );

    assertEquals("Cannot divide by zero", exception.getMessage());
}

JUnitのパラメータ化テスト

パラメータ化テストを使用すると、同じテストメソッドを異なる引数セットで実行できます。JUnit 5では、@ParameterizedTestアノテーションをデータソース(@ValueSource、@CsvSource、@MethodSource、@EnumSource)と組み合わせて使用します。

このアプローチはコードの重複を大幅に削減します。異なる値に対して10個の同一テストを書く代わりに、1つのパラメータ化されたメソッドを記述します。Google Testing Blogによると、パラメータ化によりカバレッジを損なうことなくテストコード量が40~60%削減されます。

CsvSourceの例

@CsvSourceアノテーションは、カンマ区切りの複数行をテストに渡します。各行が1回のテスト実行に対応します。JUnitは自動的に文字列値を必要な型(int、long、Stringなど)に変換します。

java
@ParameterizedTest
@CsvSource({
    "1,    1,   2",
    "2,    3,   5",
    "10,  20,  30",
    "-1,   1,   0"
})
void additionWithMultipleInputs(int a, int b, int expected) {
    assertEquals(expected, a + b);
}

複雑なオブジェクトのためのMethodSource

入力データが単純な数値や文字列より複雑な場合は、@MethodSourceを使用します。これは引数のStreamを返す静的メソッドを参照します。例えば、DAO層をテストするためのArgumentsのStreamやUserオブジェクトのStreamなどです。

JUnitとAndroidプロジェクトの統合

Android開発では、JUnitAndroidX Testと併用され、Activity、Content Provider、その他のAndroidコンポーネントをテストするための拡張機能を提供します。JUnitはエミュレータなしでJVM上で実行される単体テストを担当し、AndroidX Testはデバイス上のインストゥルメントテストを担当します。

Gradleのセットアップ

AndroidプロジェクトにJUnit 5を追加するには、モジュールレベルのbuild.gradleにorg.junit.jupiter:junit-jupiter依存関係を含めるだけで十分です。AGP Gradleプラグインは、標準のTest Runnerを介してJVM上でJUnit 5テストを実行することをサポートしています。

kotlin
// build.gradle.kts
android {
    testOptions {
        unitTests.isIncludeAndroidResources = true
    }
}

dependencies {
    testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
    testImplementation("androidx.test:core-ktx:1.6.1")
}

JUnitを使用したViewModelのテスト

実際には、JUnitはAndroidコンテキストやエミュレータを必要としないViewModelやリポジトリのテストに最もよく使用されます。このようなテストはミリ秒で実行され、時間を無駄にすることなく何百回も実行できます。

  • ViewModel — 状態の検証:loading、success、error。
  • Repository — データマッピングとエラー処理の検証。
  • UseCase — 依存関係のモックを使用したビジネスロジックの検証。

JUnit 4 vs JUnit 5:主な違い

JUnit 5(Jupiter)は単なる新しいバージョンではなく、3つのモジュールに分割された完全に再設計されたプラットフォームです:JUnit Platform(JVM上でのテスト実行)、JUnit Jupiter(テスト作成のためのAPI)、JUnit Vintage(JUnit 4との後方互換性)。このモジュール性により、さまざまなTest Engine(例:Kotlin用のSpekやTestNG)を接続できます。

特徴JUnit 4JUnit 5
パッケージorg.junitorg.junit.jupiter
基本アノテーション@Test(junit.framework)@Test(org.junit.jupiter.api)
Before/After@Before、@After、@BeforeClass@BeforeEach、@AfterEach、@BeforeAll
パラメータ化@RunWith(Parameterized.class)@ParameterizedTest + @ValueSource
拡張@Rule、@ClassRule@ExtendWith、より柔軟なAPI
Java最小Java 5Java 8+

JUnit 4からJUnit 5への移行は、すべてのテストを書き換える必要はありません。JUnit Vintage Engineを追加するだけで、古いテストは引き続き動作します。新しいテストはJUnit 5で記述することをお勧めします。拡張機能、ラムダアサーション、組み込みのパラメータ化サポートを活用できます。

よくある質問

JUnitとMockitoの違いは何ですか?

JUnitはテストを作成して実行するためのフレームワークであり、Mockitoはモックオブジェクトを作成するためのライブラリです。これらは一緒に使用されます。JUnitがテスト実行を管理し、Mockitoがテスト対象クラスの依存関係を置き換えます。

AndroidプロジェクトでJUnit 5を使用できますか?

はい、JUnit 5はAndroidプロジェクトと完全に互換性があります。単体テストの場合は、build.gradleにjunit-jupiter依存関係を追加するだけです。インストゥルメントテストは引き続きAndroidX Test Runnerを介して動作します。

テストに必要な最小限のアノテーションセットは?

最低限、メソッドの前に1つの@Testアノテーションだけで十分です。初期化とクリーンアップには@BeforeEachと@AfterEachが推奨されますが、必須ではありません。

JUnitのTest Runnerとは?

Test Runnerは、classpathをスキャンし、@Testアノテーションが付いたメソッドを見つけ、テストクラスのインスタンスを作成してテストを実行するJUnitのコンポーネントです。JUnit 5では、この役割は接続されたTest EngineとともにJUnit Platformが担います。

メソッドが例外をスローすることを確認するには?

assertThrows(Class, Executable)を使用します。これは期待される例外タイプとメソッド呼び出しを含むラムダを受け取ります。JUnitは例外が実際にスローされたことを検証し、さらに検査するためにそれを返します。

まとめ

  • JUnitはJavaとKotlinの標準単体テストフレームワークであり、xUnitエコシステムの基盤です。
  • アノテーション @Test、@BeforeEach、@AfterEachがテストクラスのライフサイクルを管理します。
  • アサーション — assertEquals、assertTrue、assertThrowsが結果の正確性を検証します。
  • パラメータ化テストは@CsvSourceと@MethodSourceでコードの重複を削減します。
  • JUnit 5 — プラットフォーム、Jupiter API、拡張機能サポートを備えたモジュラーアーキテクチャ。
  • Android統合 — JUnitはエミュレータなしで標準のTest Runnerを介してJVM上で実行されます。
  • Test Runnerが@Testメソッドを自動的に検出して実行し、結果を報告します。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください