skip to content

A team adds junit-jupiter-api and calls useJUnitPlatform(), but the build reports zero tests run. What is the most likely cause and the fix?

level: juniorimportance: must knowfreq 55%

answer

  1. API compiles, engine runs
  2. 0 tests = missing engine
  3. BUILD SUCCESSFUL but nothing ran
  4. add engine or aggregator
  5. check testRuntimeClasspath

basics

~10 s

They added only the API, not the engine. Without junit-jupiter-engine on testRuntimeOnly the Platform has nothing to discover the tests. Add the engine (or the junit-jupiter aggregator) and the tests run.

solid answer

~40 s

The classic symptom of 'compiles fine, zero tests run' is a **missing runtime engine**. `junit-jupiter-api` lets test code compile against `@Test` and `Assertions`, and `useJUnitPlatform()` tells Gradle to use the Platform — but the Platform discovers tests by asking registered `TestEngine`s, and the only thing that registers the Jupiter engine is `junit-jupiter-engine` on the **runtime** classpath. With just the API present, the launcher finds no engine, discovers no tests, and Gradle happily reports BUILD SUCCESSFUL with 0 tests. The fix is to add `testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")`, or simpler, replace the API dependency with the aggregator `testImplementation("org.junit.jupiter:junit-jupiter")` which brings the engine too. On newer Gradle, also ensure `junit-platform-launcher` is on `testRuntimeOnly`.

code

kotlin · 5 lines
kotlin
dependencies {
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.2")  // the missing piece
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

go deeper

for a junior

Recognize 'compiles but 0 tests' means the engine is missing; add it.

for a middle

Explain the compile-API/runtime-engine split and how to verify via the dependencies report.

for a senior

List the full diagnosis checklist including launcher, source set, tag filters, and wrong @Test import.

for a principal

Add a CI guard that fails the build when test count is zero so this silent failure can never ship.

## The trap: compile vs runtime JUnit 5 cleanly separates what you **compile against** (the API) from what **runs your tests** (the engine). It is entirely possible to have a project that: - compiles all test classes (API present), - has `useJUnitPlatform()` set, - yet runs **zero tests**. That is because discovery is delegated to `TestEngine`s found via ServiceLoader at runtime, and no engine is on the classpath. ## Diagnosis checklist 1. Is `junit-jupiter-engine` (or the `junit-jupiter` aggregator) on `testRuntimeOnly` / `testImplementation`? If only `-api` is declared, that is the bug. 2. Is `junit-platform-launcher` present (required on recent Gradle)? 3. Run `./gradlew test --info` — it will show the worker starting but no tests discovered. 4. Run `./gradlew dependencies --configuration testRuntimeClasspath` and grep for `junit-jupiter-engine`. ## The fix ```kotlin dependencies { // Either the explicit pair: testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.2") testRuntimeOnly("org.junit.platform:junit-platform-launcher") // Or simply the aggregator (covers the engine): // testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") } tasks.test { useJUnitPlatform() } ``` ## Bonus failure modes - Tests in the wrong source set (not `src/test/java` or `src/test/kotlin`). - A `filter`/`includeTags` that excludes everything. - Importing `org.junit.Test` (JUnit 4) instead of `org.junit.jupiter.api.Test` — the Jupiter engine then ignores them.

  • How would you confirm the engine is missing from the classpath?
    Run ./gradlew dependencies --configuration testRuntimeClasspath and look for junit-jupiter-engine. Its absence confirms the diagnosis.
  • Could importing org.junit.Test cause the same zero-tests symptom?
    Yes — that is the JUnit 4 annotation. The Jupiter engine only discovers org.junit.jupiter.api.Test, so JUnit 4 imports are ignored unless the Vintage engine is present.

saying these in an interview costs you the question

  • Concluding the build is fine because it says BUILD SUCCESSFUL with 0 tests.
  • Adding more API artifacts instead of the runtime engine.

context