Skip to content
Latchkey

Java "NoClassDefFoundError" / "ClassNotFoundException" in Tests - Fix in CI

A class compiled fine but is not on the classpath when tests run. ClassNotFoundException means the loader could not find the class at all; NoClassDefFoundError means it was present at compile time but is missing (or failed to initialize) at runtime. The usual cause is a dependency in the wrong scope/configuration.

What this error means

Tests fail not with an assertion but with NoClassDefFoundError: com/example/Foo or ClassNotFoundException: com.example.Foo in the stack trace. The compile succeeded - the gap is between the compile classpath and the test/runtime classpath.

stack trace
java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
    at com.example.OrderServiceTest.setUp(OrderServiceTest.java:21)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils

Common causes

Dependency in a compile-only / provided scope

A dependency declared provided (Maven) or compileOnly (Gradle) is on the compile classpath but not the test/runtime classpath, so the class is missing when tests run.

A missing transitive dependency or static-init failure

A required transitive jar is excluded/absent at runtime, or the class’s static initializer throws - both surface as NoClassDefFoundError the first time the class is used.

How to fix it

Put the dependency in a scope tests can see

Use test/testImplementation (or normal implementation) so the class is on the test runtime classpath.

pom.xml
<!-- Maven -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.14.0</version>
  <scope>test</scope>   <!-- not 'provided' -->
</dependency>

Inspect the test runtime classpath

Confirm the missing jar is actually present where tests run, and check for a static-init failure underneath.

Terminal
mvn -B dependency:tree -Dscope=test
# Gradle:
./gradlew :app:dependencies --configuration testRuntimeClasspath

How to prevent it

  • Choose dependency scopes deliberately - provided/compileOnly are not on the test runtime classpath.
  • Run the full test suite in CI so runtime-classpath gaps surface before release.
  • Inspect testRuntimeClasspath/dependency:tree -Dscope=test when a class goes missing.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →