A teammate's custom integrationTest suite fails to compile with 'cannot find symbol' for classes from a library that the unit tests use fine. What's the likely cause and fix, given how suite dependencies work?
answer
- suites have isolated configurations
- testImplementation not inherited by custom suites
- fix: declare in suite block or extendsFrom
- compile vs runtime scope mismatch
- missing main class -> add project()
basics
~20 sCustom suites don't inherit testImplementation. The library was declared only for the test suite, so the integration suite never saw it. Fix: declare it in the integrationTest suite's dependencies { }, or make integrationTestImplementation extend testImplementation.
solid answer
~40 sEach JVM test suite has isolated, suite-specific configurations. A dependency added under the unit-test suite (or via top-level `testImplementation`) lands only on `testImplementation`, which a custom `integrationTest` suite does **not** inherit. So the integration suite's compile classpath is missing that library — hence 'cannot find symbol'. Two fixes: (1) add `implementation(libs.thatLib)` inside the `integrationTest` suite's `dependencies { }` block; or (2) make the integration suite inherit the unit-test classpath wholesale with `configurations["integrationTestImplementation"].extendsFrom(configurations["testImplementation"])`. Don't forget `runtimeOnly`/`integrationTestRuntimeOnly` if the missing symbol only shows up at runtime. Also confirm `implementation(project())` is present if the missing symbol is a *production* class rather than a library type.
code
kotlin · 12 lines// either: declare per-suite
testing {
suites {
val integrationTest by getting(JvmTestSuite::class) {
dependencies { implementation(libs.assertj) }
}
}
}
// or: inherit the unit-test classpath
configurations["integrationTestImplementation"]
.extendsFrom(configurations["testImplementation"])go deeper
Recognize that the integration suite needs its own dependency declaration; basic fix recall.
Explain suite configuration isolation and offer both the per-suite and extendsFrom fixes, distinguishing compile vs runtime scope.
Diagnose from the error type, choose isolation vs inheritance deliberately, and cover the production-class-vs-library distinction.
Set conventions so suites neither silently inherit nor duplicate dependencies, making classpath composition explicit and reviewable across teams.
## Why it happens The `jvm-test-suite` plugin gives each suite its own configuration family: - `test` suite -> `testImplementation`, `testRuntimeOnly`, ... - `integrationTest` suite -> `integrationTestImplementation`, `integrationTestRuntimeOnly`, ... These are **independent**. A dependency declared like this: ```kotlin dependencies { testImplementation(libs.assertj) // only the test suite sees this } ``` appears on `testImplementation` alone. The custom `integrationTest` suite does not inherit it, so its compilation fails to resolve `assertj` types -> 'cannot find symbol'. ## Fix 1 — declare it in the suite block ```kotlin testing { suites { val integrationTest by getting(JvmTestSuite::class) { dependencies { implementation(project()) implementation(libs.assertj) } } } } ``` Explicit and isolated — recommended when only this suite needs it. ## Fix 2 — inherit the whole unit-test classpath ```kotlin configurations["integrationTestImplementation"] .extendsFrom(configurations["testImplementation"]) configurations["integrationTestRuntimeOnly"] .extendsFrom(configurations["testRuntimeOnly"]) ``` Good when the integration suite should share most of the unit-test stack (assertion libs, mocking, etc.). ## Distinguish the two symptoms - **Compile-time** missing symbol -> the lib must be on `*Implementation` (or `compileOnly`). - **Runtime** `NoClassDefFoundError` -> add to `*RuntimeOnly`/`*Implementation`; extending only the implementation config may miss `testRuntimeOnly` entries (e.g. a JDBC driver). ## Production class vs library class If the missing symbol is one of *your own* main classes, the root cause is a missing `implementation(project())`, not a library issue. ## Takeaway Suite isolation is the default and the usual cause of these errors. Either declare deps per-suite or wire `extendsFrom` inheritance deliberately — and match the scope (`implementation` vs `runtimeOnly`) to whether the failure is at compile or run time.
- If the missing class only appears as a runtime error, not at compile time, what changes about the fix?You must put the dependency on a runtime-bearing configuration — `runtimeOnly(...)` in the suite block or extending `integrationTestRuntimeOnly` from `testRuntimeOnly`; extending only the implementation config can miss runtime-only entries like JDBC drivers.
- How would you tell whether the missing symbol is a library type or one of your own production classes?Check the package/import: your own `main` packages mean the fix is `implementation(project())`; a third-party package means the library wasn't declared on the suite's configuration.
saying these in an interview costs you the question
- Assuming custom suites inherit `testImplementation` automatically.
- Fixing a runtime `NoClassDefFoundError` by adding only to a compile-only configuration.
- Blaming a library when the missing symbol is actually a main class needing `project()`.