skip to content

Inside a JVM test suite's dependencies block, how do you give an integrationTest suite access to your project's own main/production classes?

level: juniorimportance: must knowfreq 60%

answer

  1. suite-local dependencies { } block
  2. implementation(project()) = this project
  3. custom suites don't inherit main classpath
  4. deps go to integrationTestImplementation

basics

~10 s

Add implementation(project()) inside the suite's dependencies { } block. The bare project() call refers to the current project, so the suite compiles and runs against main classes.

solid answer

~30 s

Each JVM test suite registered via the `jvm-test-suite` plugin has its own `dependencies { }` block. To let an `integrationTest` suite see the project's own production code you add `implementation(project())` there — `project()` with no path means *this* project. Unlike the built-in `test` suite, a custom suite does **not** automatically depend on the main source set's `implementation`/`runtimeOnly` classpath, so you must wire it explicitly. You can also pull in third-party libraries (`implementation(libs.someLib)`) in the same block; those resolve against the suite's dedicated `integrationTestImplementation` configuration, keeping them isolated from the `test` suite and from `main`.

code

kotlin · 10 lines
kotlin
testing {
  suites {
    val integrationTest by registering(JvmTestSuite::class) {
      dependencies {
        implementation(project())          // see main classes
        implementation(libs.junit.jupiter)
      }
    }
  }
}

go deeper

for a junior

Recall that implementation(project()) inside the suite's dependencies block gives access to main classes.

for a middle

Explain that the suite block maps to a dedicated integrationTestImplementation configuration and that custom suites don't inherit the main classpath.

for a senior

Contrast the special built-in test suite with custom suites, and discuss classpath isolation benefits of suite-specific configurations.

for a principal

Frame suite-local dependency blocks as the mechanism enforcing classpath isolation across test tiers org-wide, avoiding leaked deps between unit and integration tests.

## What the suite `dependencies` block is The `jvm-test-suite` plugin (applied automatically by the `java` plugin) exposes a `testing { suites { } }` container. Each suite you register — e.g. `val integrationTest by registering(JvmTestSuite::class)` — gets its **own** dependency block: ```kotlin testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { implementation(project()) } } } } ``` This block is a small typed DSL (`JvmComponentDependencies`) — it is **not** the top-level `dependencies { }` of the build. Methods like `implementation(...)`, `runtimeOnly(...)`, `compileOnly(...)`, and `annotationProcessor(...)` add to **suite-specific configurations** named after the suite: `integrationTestImplementation`, `integrationTestRuntimeOnly`, etc. ## Why `project()` is needed The built-in `test` suite is special: it inherits the main source set's compile/runtime classpath, so your tests see production classes for free. A **custom** suite is wired from scratch and gets no such inheritance. `implementation(project())` adds a dependency on the current project's outgoing API/runtime variants, so the suite can `import` and execute your main classes. `project()` (empty args) = the project the build script belongs to; `project(":other")` would target a different subproject. ## Pulling in shared libraries Inside the same block you reference version-catalog or coordinate dependencies just like a normal configuration: ```kotlin dependencies { implementation(project()) implementation(libs.junit.jupiter) runtimeOnly(libs.postgresql) } ``` Because these land in `integrationTestImplementation`, they are isolated from `testImplementation` — the unit-test suite never sees them, which keeps the two classpaths clean. ## Key takeaway Custom suites are isolated by default; `implementation(project())` is the explicit bridge from a suite to your own production code, and the suite block is where all of that suite's library deps live.

  • Why doesn't the custom integrationTest suite already see main classes the way the test suite does?
    The built-in `test` suite is special-cased to inherit the main source set's compile/runtime classpath. Custom suites are wired independently and inherit nothing, so you add `implementation(project())` explicitly.
  • What configuration does `implementation(...)` inside the integrationTest suite actually contribute to?
    `integrationTestImplementation` — a suite-specific configuration created by the plugin, isolated from `testImplementation` and from `main`'s `implementation`.

saying these in an interview costs you the question

  • Claiming `project()` needs the project path of the current project — bare `project()` already means the current project.
  • Assuming a custom suite inherits the main classpath automatically like the `test` suite does.

context