skip to content

Test Fixtures Dependencies

The java-test-fixtures plugin and consuming testFixtures(project(':lib')) so shared test helpers never leak into production code. Interviewers raise it as the clean replacement for a hand-rolled test-jar dependency.

on this pageshow

questions

5

What are test fixtures in Gradle, and how do you enable them in a project?

level: juniorimportance: must knowfreq 55%

answer

  1. java-test-fixtures plugin
  2. src/testFixtures/java source set
  3. testFixturesApi vs testFixturesImplementation
  4. separate -test-fixtures jar / variant
  5. own test gets fixtures automatically

basics

~10 s

Test fixtures are reusable test helper code (builders, fakes, sample data) shared across test classes and other projects. Enable them by applying the java-test-fixtures plugin, then put code in src/testFixtures/java.

solid answer

~40 s

Test fixtures are shared test-support code — object mothers, fakes, assertion helpers, sample data — that you don't want to duplicate across test classes or modules. Gradle's built-in `java-test-fixtures` plugin formalizes this: apply it and Gradle creates a new `testFixtures` source set at `src/testFixtures/java` plus dedicated `testFixturesApi`/`testFixturesImplementation` configurations. The project's own `test` source set automatically gets the fixtures on its compile/runtime classpath, so tests can use them with no extra wiring. The fixtures are also packaged into a separate artifact (a `-test-fixtures` classifier jar) with its own variant, so other projects can consume them via `testFixtures(project(':lib'))`. It depends on `java` or `java-library`, so apply it alongside one of those.

code

kotlin · 11 lines
kotlin
plugins {
    `java-library`
    `java-test-fixtures`
}

dependencies {
    // visible to consumers of the fixtures
    testFixturesApi("org.assertj:assertj-core:3.25.3")
    // internal to the fixtures only
    testFixturesImplementation("com.github.javafaker:javafaker:1.0.2")
}

go deeper

for a junior

Know that java-test-fixtures exists, that fixture code lives in src/testFixtures/java, and that it's for sharing test helpers.

for a middle

Explain the auto-created configurations and source set, the api/implementation split, and that the module's own tests use fixtures for free.

for a senior

Discuss the separate variant/capability, the published -test-fixtures jar, and why explicit opt-in keeps test code out of runtime.

for a principal

Frame fixtures as a way to standardize test-support code across a multi-module codebase and weigh them against a dedicated shared test module.

## What problem test fixtures solve In real projects you accumulate test-support code that isn't a test itself: object builders ("object mothers"), in-memory fakes, custom assertions, sample JSON, random data generators. If this lives in `src/test`, only that module's tests can use it. Copy-pasting it into downstream modules is the usual hack. Gradle's **`java-test-fixtures`** plugin gives this code a first-class home. ## What the plugin does Applying it (it requires `java` or `java-library`): - Creates a new **source set** `testFixtures` rooted at `src/testFixtures/java` (and `resources`). - Creates configurations **`testFixturesApi`** and **`testFixturesImplementation`** (mirroring the `api`/`implementation` split — `testFixturesApi` dependencies leak onto the consumer's compile classpath, `testFixturesImplementation` stay internal). - Wires the project's own `test` source set to compile and run against the fixtures automatically. - Produces a separate **artifact/variant** (jar with the `test-fixtures` classifier) and an outgoing **`testFixturesApiElements`/`testFixturesRuntimeElements`** configuration so other modules can resolve it. ## Consuming fixtures From another project's test code: ```kotlin dependencies { testImplementation(testFixtures(project(":lib"))) } ``` The `testFixtures(...)` helper selects the fixtures variant rather than the main variant. You can also consume published fixtures from an external module with `testFixtures("com.example:lib:1.0")`, provided the producer published Gradle Module Metadata describing that variant. ## Why a separate variant, not just another jar Gradle uses **variant-aware resolution** — each artifact carries attributes describing its capabilities. The fixtures jar advertises a distinct *capability* (`group:name-test-fixtures`), so consumers must explicitly opt in with `testFixtures(...)`; they won't get fixtures by accident on the production classpath. This keeps test-only helpers out of your runtime distribution.

  • Where does fixture source code live, and what is the configuration to add a third-party library only to the fixtures?
    Code goes in `src/testFixtures/java`. Use `testFixturesImplementation` for libraries internal to the fixtures, or `testFixturesApi` if the dependency's types appear in the fixtures' public API and should reach consumers.
  • Does the producing module's own tests need extra wiring to use the fixtures?
    No. The plugin automatically puts the `testFixtures` output on the `test` source set's compile and runtime classpath, so the module's own tests use them with zero extra configuration.

saying these in an interview costs you the question

  • Claiming you must manually add the fixtures source set or configurations — the plugin creates them.
  • Saying fixtures end up on the production/runtime classpath of consumers automatically (they require explicit opt-in via testFixtures(...)).

context

open as a page

How do you consume test fixtures from another project in the same build, and how does it differ from consuming published external fixtures?

level: middleimportance: must knowfreq 50%

basics

~10 s

Use the testFixtures() helper inside a dependency declaration: testImplementation(testFixtures(project(":lib"))) for a local project, or testImplementation(testFixtures("g:a:v")) for an external module. External requires the producer to publish Gradle Module Metadata.

open as a page

Explain the difference between testFixturesApi and testFixturesImplementation. When should a fixture dependency go in each?

level: middleimportance: should knowfreq 38%

basics

~20 s

testFixturesApi dependencies are part of the fixtures' public API and leak onto consumers' compile classpath; testFixturesImplementation ones are internal to the fixtures and only reach consumers at runtime. Put a library in Api only if its types appear in fixture signatures.

open as a page

Why might you prefer Gradle's java-test-fixtures over a hand-rolled shared test-utilities module? What are the trade-offs?

level: seniorimportance: should knowfreq 30%

basics

~20 s

java-test-fixtures keeps fixtures inside the module they support, ships them as a separate opt-in variant (not on production classpaths), and requires no extra module. A shared 'test-utils' module is simpler to grasp but scatters helpers away from their owner and risks leaking onto runtime.

open as a page

What do you need to publish and consume test fixtures of an external library, and what common pitfalls arise?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

The producer must apply java-test-fixtures, use maven-publish, and publish Gradle Module Metadata (the .module file) so the fixtures variant is described. Consumers then use testFixtures("g:a:v"). Common pitfalls: metadata not published, or the producer thinking a POM is enough.

open as a page