skip to content

After switching a Gradle module to useJUnitPlatform(), the build reports 'No tests found for given includes' or silently skips the old tests. What likely went wrong and how do you fix it?

level: middleimportance: should knowfreq 45%

answer

  1. useJUnitPlatform() needs a matching engine
  2. Missing Vintage = 0 tests, silent green
  3. testRuntimeOnly junit-vintage-engine fixes it
  4. starter-test excludes junit:junit
  5. check for leftover filter/--tests pattern

basics

~10 s

The Vintage engine is missing from the test runtime classpath, so the Platform has no engine to run the JUnit 4 tests. Add testRuntimeOnly('org.junit.vintage:junit-vintage-engine') so they're discovered.

solid answer

~40 s

When you call `useJUnitPlatform()`, Gradle hands discovery to the JUnit Platform `Launcher`, which only runs tests an **engine** claims. If you switched away from JUnit 4's legacy runner but did **not** add the Vintage engine, no engine recognizes the old `org.junit.Test` classes, so the Platform finds zero tests and Gradle reports 'No tests found' (or the tests are silently skipped). The fix is to put `org.junit.vintage:junit-vintage-engine` on `testRuntimeOnly` so Vintage is `ServiceLoader`-discovered and claims those classes. Related gotchas: ensure `junit:junit` is still present (some BOMs/starters exclude it), don't accidentally have only `junit-jupiter-engine` on the classpath, and check no `filter`/`includeTestsMatching` in the `Test` task is over-restricting discovery. With Vintage present, the count goes from 0 back to the full JUnit 4 suite.

code

bash · 4 lines
bash
# Confirm the engine is actually on the runtime classpath
./gradlew dependencies --configuration testRuntimeClasspath | grep vintage
# Run with engine logging to see what the Platform loaded
./gradlew test --info | grep -i engine

go deeper

for a junior

Recognize that 0 tests after useJUnitPlatform() usually means the Vintage engine is missing; add it on testRuntimeOnly.

for a middle

Enumerate the causes — missing engine, excluded junit:junit, over-restrictive filter — and diagnose via the testRuntimeClasspath.

for a senior

Recommend failing the build on zero discovered tests so silent regressions are caught in CI.

for a principal

Standardize a convention plugin that wires platform+engines correctly and a CI check that flags suspiciously low/zero test counts across modules.

## The symptom You migrate a module's `test` task to the Platform: ```kotlin tasks.named<Test>("test") { useJUnitPlatform() } ``` and suddenly Gradle prints either `No tests found for given includes` (when a filter is set) or just runs **0 tests** while the build stays green. The JUnit 4 tests that used to run have vanished. ## Root cause: no engine claims the tests Under `useJUnitPlatform()`, Gradle does **not** run JUnit 4 tests itself anymore. It delegates to the JUnit Platform `Launcher`, which loads every `TestEngine` registered via the JVM `ServiceLoader` and asks them to discover tests. If the only engine present is `junit-jupiter-engine`, then: - Jupiter inspects your `org.junit.Test`-annotated classes and **does not recognize them** (wrong annotation package). - No other engine is present to claim them. - Result: zero tests discovered. The legacy JUnit 4 runner that Gradle used *before* `useJUnitPlatform()` is gone, and nothing replaced it for those classes. ## The fix ```kotlin dependencies { testImplementation("junit:junit:4.13.2") // still need the API to compile testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.10.2") } ``` Adding Vintage gives the Platform an engine that claims `org.junit.Test`/`@RunWith`/`TestCase` classes. Re-run and the count returns to the full suite. ## Other causes that produce the same symptom 1. **`junit:junit` got excluded.** `spring-boot-starter-test` historically excludes `junit:junit`. If you removed it (or relied on a BOM that drops it), the JUnit 4 tests no longer compile or are no longer recognized. Re-add the API. 2. **Over-restrictive filtering.** A leftover `filter { includeTestsMatching("...") }` or `--tests` pattern on the `Test` task can legitimately yield 'No tests found for given includes'. Confirm the pattern. 3. **Wrong source set / no test classes compiled.** If nothing compiled into `build/classes/java/test`, there is nothing to discover regardless of engines. 4. **`failOnNoDiscoveredTests`.** Newer Gradle/JUnit can be configured to fail when zero tests are discovered — useful to turn a silent skip into a loud error so you notice the missing engine. ## How to diagnose quickly - Run with `--info` and look for the engines the Platform loaded. - Print the test runtime classpath: `./gradlew dependencies --configuration testRuntimeClasspath` and grep for `junit-vintage-engine`. - Temporarily add one Jupiter test; if *it* runs but JUnit 4 ones don't, the engine for Vintage is the missing piece. ## The lesson `useJUnitPlatform()` and 'the right engine on testRuntimeOnly' are a **pair**. Flipping one without the other is the single most common Vintage migration bug.

  • Why does the build often stay green instead of failing when this happens?
    Zero discovered tests is not an error by default — the Platform simply finds nothing to run, so the task succeeds vacuously. You can make Gradle fail on no-discovered-tests to surface it loudly.
  • You added Vintage but tests still don't compile. What else?
    The JUnit 4 API (junit:junit) may be missing or excluded (e.g. by spring-boot-starter-test). Vintage is only the runtime engine; the @Test/@RunWith annotations need junit:junit on testImplementation to compile.

saying these in an interview costs you the question

  • Assuming useJUnitPlatform() alone runs JUnit 4 tests — it needs the Vintage engine.
  • Treating a green build with 0 tests as success without checking the test count.
  • Adding only junit-jupiter-engine and expecting it to pick up org.junit.Test classes.

context