mcpField
J
java-junit

java-junit

github.com/githubテスト・品質40.5k11.7k 回インストール今日更新
リポジトリ

java-junit について

JUnit 5/6、AssertJ、Mockito を使った Java テストのガイダンスを提供するスキルです。既存の規約に従い、決定的なテストと安全なテスト運用を重視します。

主な機能

  1. 01既存のビルド・テスト規約の確認
  2. 02JUnit 5/6 のガイダンス
  3. 03アサーションと Mockito の実践
  4. 04決定的なテストの手法
  5. 05単体・統合テストの設定
  6. 06テストの安全性と検証ルール

活用シーン

  1. 01既存の Java プロジェクトへのテスト追加
  2. 02不安定なテストから時間や乱数依存を除去
  3. 03単体テストと統合テストの実行分離

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/github/awesome-copilot --skill java-junit

インストール後、Claude Code で/java-junitを入力して読み込まれたか確認します。

同梱ファイルreferences/assertj-and-mockito.mdreferences/build-setup.md

詳細

JUnit 5/6、AssertJ、Mockito による Java テスト

高速で決定的なユニットテストのための、フレームワークに依存しないガイダンスです。Spring のスライスには spring-boot-testing(インストールされている場合)を、Docker で実際のデータベースやブローカーを使う場合は java-testcontainers を使用してください。原因を説明できない失敗には java-debugging を使用してください。

まず、押し付けずに検出する

  1. pom.xml/build.gradle* を読み、JUnit のバージョン(junit-jupiter、junit-bom、または Spring Boot BOM からの継承)、アサーションライブラリ、Mockito、Surefire/Failsafe のバージョン、Java のリリースを確認します。
  2. 既存の src/test/java の規約(命名、アサーションライブラリ、static import、モックのスタイル)に合わせます。既存プロジェクトにない場合は、確認せずに AssertJ、Mockito、JaCoCo を導入しないでください。
  3. JUnit のメジャーバージョンを暗黙に上げないでください。アップグレードは独立したタスクです(インストールされている場合は java-upgrade を参照してください)。

JUnit 5 と JUnit 6

JUnit 5(最終版 5.14.x)JUnit 6(6.0 リリース済み。現在のバージョンは 6.1.x)
Java のベースライン817(公開済みの Gradle モジュールメタデータで確認済み)
バージョニングPlatform 1.x、Jupiter 5.x、Vintage 5.xPlatform、Jupiter、Vintage で共通のバージョン番号
APIorg.junit.jupiter.api.*同じパッケージです。このスキルの Jupiter テストは、5.14.4 と 6.0.3 のどちらでも変更なしでコンパイルおよび実行できます
6.0 で削除MethodOrderer.Alphanumeric、非推奨の2引数版 InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext) オーバーロード(3引数版は引き続き使用できます)、junit.jupiter.tempdir.scope、@CsvFileSource(lineSeparator)
CSVunivocity-parsersFastCSV:解析がより厳格になり(閉じ引用符の後に文字を置けません)、ヘッダーフィールドのオプションがヘッダーにも適用されるようになりました
その他junit-jupiter-migrationsupport は非推奨です。列挙型形式の設定値が無効な場合、ディスカバリーに失敗するようになりました。@Nested クラスの順序は決定的ですが、直感的ではありません

出典:JUnit 6.0.0 のリリースノート(https://docs.junit.org/6.0.0/release-notes.html)。対象バージョンのリリースノート(https://docs.junit.org/current/release-notes/)を確認し、この表よりも優先してください。JUnit 4 のテストには Vintage エンジンが必要です。同じクラス内で org.junit.Test と org.junit.jupiter.api.Test を混在させないでください。

依存関係(5 と 6 で共通。Maven と Gradle で確認済み):org.junit:junit-bom をインポートし、test スコープで org.junit.jupiter:junit-jupiter(api、params、engine を集約)を宣言します。Gradle 9 ではさらに testRuntimeOnly("org.junit.platform:junit-platform-launcher") が必須です(確認済み:これがないとテスト実行エンジンは "Failed to load JUnit Platform" で失敗します)。また、tasks.test { useJUnitPlatform() } も必要です。Maven では Surefire 3.x が必要です(3.6.0 で確認済み)。

アサーション

プロジェクトで使われているライブラリに合わせます。Jupiter の基本ルールは、期待値を先に指定すること、遅延評価される Supplier メッセージ、assertAll、assertThrowsExactly、タイムアウトです。(別の instructions/java-junit5-assertions.instructions.md リソースには詳しい説明がありますが、このスキルにはインストールされません。)プロジェクトで AssertJ を使用している場合は、コレクション、文字列、例外には AssertJ を優先してください。パターン(ソフトアサーション、assertThatThrownBy、extracting、containsExactly、usingRecursiveComparison)は references/assertj-and-mockito.md にあります。

  • 内部処理が何回呼び出されたかではなく、結果と状態をアサートします。
  • 値を比較し、単独の assertNotNull は避けてください。
  • テストを通すために AssertionError/Exception を決して捕捉しないでください。

モック化(Mockito)

  • 境界をまたぐ協調オブジェクト(リポジトリ、HTTP クライアント、クロック、メッセージ送信機)をモック化します。値オブジェクト、レコード、コレクション、String、テスト対象のクラスはモック化せず、実際のインスタンスまたは簡単なフェイクを使います。
  • インタラクションが状態を持つ場合は、モックより手書きのフェイクを優先します。
  • @ExtendWith(MockitoExtension.class) と @Mock/@InjectMocks/@Captor を使います。ここでは厳格なスタブがデフォルトのため、未使用のスタブがあるとテストは失敗します(UnnecessaryStubbingException)。テストを修正してください。正当な理由がある共有セットアップに限り、@MockitoSettings(strictness = Strictness.LENIENT) で緩和します。
  • Mockito 5 では、デフォルトでインラインモックメーカーが使われます。JDK 21 以降では、自己アタッチして動的エージェントに関する警告が表示されることがあります。Mockito 5.14.0 以降では、代わりに mockito-core を -javaagent として登録します(Maven と Gradle のセットアップは references/assertj-and-mockito.md を参照。JDK 21 と 25 で検証済み)。まず解決済みのバージョンを確認してください。それ以前の 5.x の JAR には Premain-Class がなく、エージェントとして使用できません。アップグレードする前に確認してください。それ以外の場合は、インストール済みのバージョン向けに文書化されている計測セットアップを使用します。
  • Mockito 5 には Java 11 以降が必要です。デフォルトのインラインモックメーカーは GraalVM ネイティブイメージでは動作しません。その場合はサブクラスモックメーカーが適切です(Mockito 5.0.0 リリースノート、https://github.com/mockito/mockito/releases/tag/v5.0.0)。
  • mockStatic/mockConstruction は避け、静的呼び出しをインターフェースの背後にラップします。

決定性

  • 時刻:java.time.Clock(Clock.fixed(...))を注入して Instant.now(clock) を呼び出します。テスト対象のコードでは Instant.now()/LocalDate.now() を避けます。
  • 乱数:固定シードの Random/RandomGenerator を注入します。生成した場合はシードをログに記録します。
  • デフォルトのロケール、タイムゾーン、ファイルエンコーディング、ネットワーク、実時間のスリープに依存しないでください。明示的に設定します(新しい 6.x リリースではロケール、タイムゾーン、システムプロパティ向けの組み込み拡張が追加されています。お使いのバージョンのリリースノートを確認し、それ以外の場合は try/finally を使用してください)。

ユニットテストと統合テスト

ユニット(*Test)統合(*IT)
MavenSurefire、mvn testFailsafe、mvn verify
Gradletest タスクcheck に組み込まれた個別の integrationTest タスク(JVM Test Suite)
速度ミリ秒単位、I/O なしDocker/DB を使う場合があります

Surefire のデフォルトでは *Test、Test*、*Tests、*TestCase が選ばれます。Failsafe では *IT、IT*、*ITCase が選ばれます。Failsafe には integration-test と verify のゴールをバインドする必要があり、mvn test ではなく mvn verify で実行します。代わりに @Tag で分けることもできます。データベースとブローカーについては java-testcontainers を、Spring のスライスについては spring-boot-testing を参照してください。ビルド設定の全例は references/build-setup.md を参照してください。

カバレッジとミューテーションテスト(任意)

  • JaCoCo:プロジェクトで使用している場合、またはユーザーが求めた場合に限り追加します。Surefire/Failsafe では、JaCoCo エージェントが上書きされないように <argLine>@{argLine} ...</argLine> を使います。
  • カバレッジは問題を検出するための指標であり、目標ではありません。数値を上げるためにアサーションのないテストを追加しないでください。また、プロジェクトにないカバレッジゲートを追加しないでください。
  • PIT(ミューテーションテスト)は時間がかかります。プロジェクトですでに使用している場合、またはユーザーが求めた場合に限り、変更したクラスのみを対象に実行します(検証済みの pitest-maven と JUnit 5 プラグインの実行記録がある references/build-setup.md を参照してください)。

エージェントのガードレール

  1. テストを成功させるために、失敗するテストを削除したり、コメントアウトしたり、@Disabled を付けたり、弱めたり(アサーションを緩くする、許容範囲を広げる、例外を握りつぶすなど)、スキップしたりしてはいけません。原因を特定してください。
  2. テストと本番コードのどちらが誤っているか判断してください。修正によって本番環境での動作が変わる場合は、いったん作業を止めて、先にユーザーに確認してください。テストに明らかに古い期待値が記述されている場合は、その旨を伝え、変更案を提示してください。
  3. ビルドを成功させるために、-DskipTests、-Dmaven.test.skip、-x test、failIfNoTests=false を追加してはいけません。
  4. 正しさを「証明」するために、テスト対象のクラスをモックしたり、モックの内部状態をアサートしたりしてはいけません。
  5. まず対象を絞ったテストを実行し、その後、ビルド全体を実行してください。
    • Maven:mvn -q -Dtest=OrdersTest test(メソッドを1つ指定する場合:-Dtest='OrdersTest#place_should_saveAndNotify_when_itemValid')、次に mvn verify。
    • Gradle:./gradlew test --tests 'demo.OrdersTest'、次に ./gradlew check。 プロジェクトラッパー(./mvnw、./gradlew)がある場合は、そちらを優先してください。
  6. 不安定なテストの場合は、再実行して再現させてから、非決定性の原因(時刻、実行順序、共有状態、非同期処理の待機)を取り除いてください。リトライを追加してはいけません。
  7. 新しいコードには、既存のテストと同じスタイルで、既存のテストの隣に新しいテストを追加してください。正常系、境界条件、エラーケースを網羅してください。

参考資料

  • references/assertj-and-mockito.md:AssertJ のパターン、Mockito の厳格性/キャプター/エージェントの設定、モックを避けるべき場合。
  • references/build-setup.md:JUnit 5/6、Failsafe の分割、JaCoCo、PIT に対応した Maven および Gradle(Kotlin DSL)の設定。

コメント