Files
asmhatre fd3434c42d Add testcontainers2 module: Testcontainers 2.0 artifact renames, JUnit 4 removal, and the Docker API version bump
Verifies five claims against primary sources rather than release-note prose: the
org.testcontainers:junit-jupiter -> testcontainers-junit-jupiter rename (and the other 60 like
it, per OpenRewrite's own Testcontainers2Migration recipe), that GenericContainer no longer
implements org.junit.rules.TestRule anywhere in the 2.0.5 jar (confirmed exhaustively, not just
for this one class), the real compiler/dependency-resolution breaks from bumping only a version
number on existing JUnit 4 @ClassRule code, the literal 1.32 -> 1.44 default Docker API version
bump in DockerClientProviderStrategy's bytecode (tied to the real Docker Engine 29 compatibility
issue), and Spring Boot 4.1.1's BOM pinning 2.0.5. Built and tested with no Docker daemon
available; one test class demonstrates a clean @EnabledIfDockerAvailable skip, guarded at the
class level after the method-level guard was caught failing first.
2026-10-08 13:19:23 +00:00
..

testcontainers2

Companion module for Migrating to Testcontainers 2.0: Artifact Renames, Package Moves and JUnit 6 on ankurm.com.

What this is

Testcontainers 2.0 shipped on 2025-10-14 as a deliberately disruptive release: 61 artifacts renamed, JUnit 4 support dropped from the type hierarchy itself (not deprecated — removed), and a default Docker API version bump that quietly fixes a real compatibility break with current Docker Engine releases. This module verifies each of those claims against a real jar, a real Maven Central artifact history, or a real compiler run — never against a changelog's prose alone — and runs the result against real JUnit 6.1.3. No docs/NN-topic.md chapters; everything beyond what fits in the post itself is in the Javadoc on the two committed test classes and in the captured transcripts below.

This module was built and tested in a sandbox with no Docker daemon available. Both test classes run (or cleanly skip) without one; nothing here asserts on a real container's output.

Self-correction made before this module was finished: the first draft of NewPostgresContainerSkipsCleanlyTest put @EnabledIfDockerAvailable on the test method. That compiles, and it is wrong — see the Javadoc on that class and docs/output/01-guard-on-method-still-fails.txt for the real failure it produced before the fix.

Versions

Dependency Version Verified against
Testcontainers 2.0.5 testcontainers-bom-2.0.5.pom; same version data-jpa-testcontainers verified Spring Boot 4.1.1's own BOM pins
JUnit Jupiter 6.1.3 maven-metadata.xml, <release>
AssertJ 3.27.7 maven-metadata.xml, <release>
JUnit 4 (test-scope only, for the reflective check) 4.13.2 pinned deliberately — see GenericContainerNoLongerImplementsTestRuleTest
JDK 25 (Temurin) java -version, this module's own build

Quickstart

mvn test   # 3 tests run; 1 skips cleanly, 0 failures

Test classes

Class What it proves Needs Docker Outcome here
GenericContainerNoLongerImplementsTestRuleTest GenericContainer implemented org.junit.rules.TestRule by inheritance in 1.21.4; zero classes anywhere in the 2.0.5 core jar implement it No Pass
NewPostgresContainerSkipsCleanlyTest The relocated, non-generic org.testcontainers.postgresql.PostgreSQLContainer compiles and runs under JUnit 6, guarded correctly (class-level) by @EnabledIfDockerAvailable Yes (guarded) Skipped

Captured output

File Contents
docs/output/00-full-test-run.txt mvn clean test — 3 tests, 1 clean skip, build green, with the guard on the class
docs/output/01-guard-on-method-still-fails.txt The same class with @EnabledIfDockerAvailable on the method instead — a real IllegalStateException from GenericContainer.start(), because TestcontainersExtension.beforeAll starts every @Container field before any method-level condition runs
docs/output/02-genericcontainer-testrule-removed-javap.txt javap proof of the TestRule removal: present via inheritance in 1.21.4, absent — exhaustively, jar-wide — in 2.0.5
docs/output/03-docker-api-version-bump-javap.txt javap proof that the hardcoded default Docker API version moved from 1.32 to 1.44 between 1.21.4 and 2.0.5, tied to the real GitHub issue where Docker Engine 29 rejects API 1.32 outright
docs/output/04-legacy-pom-compiles-under-1.21.4.txt A classic @ClassRule public static PostgreSQLContainer<?> JUnit 4 test, compiling clean against 1.21.4 with no extra dependency
docs/output/05-legacy-pom-fails-to-resolve-under-2.0.5.txt The identical source file; only the version property changed to 2.0.5. The build fails before it even reaches the TestRule question, because org.testcontainers:postgresql has no 2.0.5 release at all
docs/output/06-maven-central-artifact-history.txt The real maven-metadata.xml for both org.testcontainers:junit-jupiter (frozen at 1.21.4) and org.testcontainers:testcontainers-junit-jupiter (starts at 2.0.0) — the permanent fork point behind the rename

What's sourced from documentation, not run here

The full 61-artifact rename list and the composite Testcontainers2Migration OpenRewrite recipe are quoted from OpenRewrite's own published recipe catalog, not executed in this sandbox — see the post for the exact quotes and the link. Everything else above was compiled, run, or pulled directly from a real jar or a real Maven Central response in this sitting.