How to Fix the 'Cannot Find Symbol' Error with mvn test

Seeing error: cannot find symbol when your code compiles in the IDE but fails under mvn test is one of the most confusing Maven experiences. The fix is almost always a discrepancy between what the IDE considers on the classpath and what Maven does.

What the error means

[ERROR] /src/test/java/com/example/UserServiceTest.java:[15,8]
        cannot find symbol
  symbol:   class User
  location: package com.example.model

The compiler could not resolve an identifier β€” a class, method or variable name. Five common causes:

1. Missing import

The class exists but was never imported. The IDE usually adds imports automatically; command-line javac does not.

// Missing this line:
import com.example.model.User;

public class UserServiceTest {
    private User u = new User(); // ← cannot find symbol
}

2. Dependency declared with the wrong scope

A very common trap: a helper class is in your test sources but referenced from main sources, or vice-versa.

<!-- This makes Mockito visible in tests but NOT in main code -->
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>5.14.0</version>
  <scope>test</scope>
</dependency>

If you try to use a test dependency from production code, you get cannot find symbol. Move the scope to compile (or remove the <scope> tag) if the class is needed in both.

3. A multi-module dependency not installed

In a multi-module Maven project, module B that depends on module A will not see A's latest changes unless A has been installed first. Run the install target on the parent project:

mvn clean install -DskipTests
mvn test -pl module-b

Without this, Maven uses whatever stale artifact is in the local repository (~/.m2/repository).

4. Java source / target version mismatch

If you use language features from Java 17 (var, records, sealed classes, pattern matching) but the compiler is set to Java 8, every new API shows up as cannot find symbol.

<properties>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
</properties>

Check the JDK that Maven uses with mvn -version. If it differs from your IDE's JDK, align them.

5. Stale target/ directory

Occasionally the incremental compiler keeps a broken state. A clean build solves it:

mvn clean test

Delete target/ manually if clean itself fails for any reason.

Systematic diagnostic

  1. Read the exact symbol name. It tells you whether it is a class, method, or variable, and in which package.
  2. Find where the symbol is defined. Use grep -r "class SymbolName" src/ or the IDE's Go to Definition.
  3. Check the scope. Is it in src/main/java or src/test/java? Is the file in the module you think it is?
  4. Inspect the effective POM. Run mvn help:effective-pom and look for the dependency and its scope.
  5. Verify the dependency tree.
    mvn dependency:tree | grep -i <artifactId>
  6. Rebuild from clean.
    mvn clean install -U
    The -U flag forces a re-download of snapshot dependencies.

Pitfall: test dependencies referenced in main

Reordering a project often moves a utility class from src/test/java into src/main/java. If its dependencies were marked <scope>test</scope>, the main compilation breaks. The fix is either to move the class back, or to broaden the dependency scope.

Pitfall: IntelliJ's "delegate to Maven" setting

IntelliJ can run builds either via its internal compiler or via Maven. If they disagree on the JDK, one works and the other fails. Under Settings β†’ Build β†’ Build Tools β†’ Maven β†’ Runner, set Delegate IDE build/run actions to Maven so the two paths stay identical.

In the vast majority of cases, mvn clean install -U followed by a fresh mvn test resolves the issue. When it doesn't, the scope mismatch (cause #2 above) is the next most likely culprit.