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.
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.StringUtilsCommon 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.
<!-- 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.
mvn -B dependency:tree -Dscope=test
# Gradle:
./gradlew :app:dependencies --configuration testRuntimeClasspathHow to prevent it
- Choose dependency scopes deliberately -
provided/compileOnlyare 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=testwhen a class goes missing.