4.6 KiB
data-jpa-testcontainers
Companion module for @DataJpaTest with Testcontainers @ServiceConnection on Spring Boot 4.1 on ankurm.com.
What this is
Six JUnit 5 test classes against one JPA repository (Product), each isolating one fact about
what @DataJpaTest's default embedded-database substitution actually does, what
@ServiceConnection wires in its place, and what the defaults do not do (Flyway migrations are
not one of them). No docs/NN-topic.md chapters — everything beyond what fits in the post itself
is in the Javadoc on these six test classes and in the captured transcripts below.
This module was built and tested in a sandbox with no Docker daemon available. Five of the six test classes run and pass (or cleanly skip) without one. The sixth demonstrates, on purpose, the real failure you get from the one case that genuinely needs a container. See the versions table and the test table below for exactly which is which.
Versions
| Dependency | Version | Verified against |
|---|---|---|
| Spring Boot | 4.1.1 | spring-boot-dependencies-4.1.1.pom |
| Testcontainers | 2.0.5 | same BOM; testcontainers-bom-2.0.5.pom |
| Flyway | 12.4.0 | same BOM |
| Hibernate ORM | 7.4.5.Final | runtime log, this module's own test run |
| H2 | 2.4.240 | runtime log, this module's own test run |
| JDK | 25 (Temurin) | java -version, this module's own build |
Quickstart
mvn test # 6 of 7 run; 1 skips cleanly
mvn test -Dtest=ServiceConnectionWithoutGuardFailsToStartTest # the one deliberate failure
Test classes
| Class | What it proves | Needs Docker | Outcome here |
|---|---|---|---|
DefaultReplacementTest |
Plain @DataJpaTest substitutes an embedded H2 DataSource, and each test method is rolled back independently of execution order |
No | Pass |
FlywayDoesNotRunUnderPlainDataJpaTestTest |
@DataJpaTest's own auto-configuration import list never includes FlywayAutoConfiguration or LiquibaseAutoConfiguration — your migrations never run, substitution or not |
No | Pass |
FlywayRunsWhenExplicitlyImportedTest |
The one-line fix: @ImportAutoConfiguration(FlywayAutoConfiguration.class) |
No | Pass |
NoSubstitutionStillSilentlyUsesH2Test |
@AutoConfigureTestDatabase(replace = Replace.NONE) alone is not a guarantee of a real connection — with nothing else configured, ordinary DataSourceAutoConfiguration still silently hands you embedded H2 |
No | Pass |
ServiceConnectionSkipsCleanlyTest |
The intended shape: @ServiceConnection + @Container + replace = Replace.NONE, guarded by Testcontainers 2.0's new @EnabledIfDockerAvailable |
Yes (guarded) | Skipped |
ServiceConnectionWithoutGuardFailsToStartTest |
The same class, minus the guard | Yes (unguarded) | Fails — on purpose. Excluded from mvn test by name in pom.xml; run it explicitly |
Captured output
| File | Contents |
|---|---|
docs/output/00-full-test-run.txt |
mvn clean test — 7 tests, 1 skip, build green |
docs/output/01-postgresqlcontainer-relocation-javap.txt |
javap proof that org.testcontainers.postgresql.PostgreSQLContainer (2.0.5's new home) and the deprecated org.testcontainers.containers.PostgreSQLContainer shim live in the same jar, and that the old class alone keeps the self-referential <SELF extends ...> generic |
docs/output/02-serviceconnection-unaffected-javap.txt |
javap proof that JdbcContainerConnectionDetailsFactory is typed against org.testcontainers.containers.JdbcDatabaseContainer<?> — unmoved by the 2.0 package split, which is why @ServiceConnection needed no changes |
docs/output/04-service-connection-without-guard-fails.txt |
The real ContainerFetchException / IllegalStateException from trying to start a Postgres container with no Docker daemon present, and no guard against that |
docs/output/05-service-connection-skips-cleanly.txt |
The same absence of Docker, this time behind @EnabledIfDockerAvailable — one line, Skipped: 1, no failure |
What's sourced from code, not run here
Two things this article discusses are backed by reading Spring Boot's and Testcontainers' own
class files and import manifests rather than by a run in this sandbox, and are called out as such
in the post itself: what a successful real-Postgres run under @ServiceConnection would actually
return once a Docker daemon is present (the wiring is verified; the live round trip is not), and
Testcontainers' reusable-container feature (.withReuse(true) plus ~/.testcontainers.properties),
which has nothing to do with Docker availability but was out of scope for a module built in one
sitting.