Correct post #45: Flyway and Liquibase DO run under @DataJpaTest by default

The previous commit's FlywayDoesNotRunUnderPlainDataJpaTestTest and
FlywayRunsWhenExplicitlyImportedTest rested on a false premise: that none of
@DataJpaTest's four documented meta-annotations import FlywayAutoConfiguration,
so migrations never run under the slice. That reading of the four .imports
manifests is accurate but incomplete. @AutoConfigureJdbc is itself
meta-annotated with @AutoConfigureDataSourceInitialization (new in Boot 4.0),
and Spring's ImportAutoConfigurationImportSelector walks the full
meta-annotation tree transitively. That fifth annotation's own .imports
resource is loaded via ClassLoader.getResources(), which merges same-named
files from every jar on the classpath -- spring-boot-jdbc-test,
spring-boot-flyway and spring-boot-liquibase each ship one at the identical
path, contributing DataSourceInitializationAutoConfiguration,
FlywayAutoConfiguration and LiquibaseAutoConfiguration respectively.

Replaced the two wrong-premise test classes with FlywayRunsByDefaultTest
(proves the bean is present and the migration actually ran) and
ExplicitFlywayImportIsRedundantTest (proves the old "add the import yourself"
advice is harmless but unnecessary on Boot 4.1). Added javap/unzip evidence
for the new mechanism to docs/output, re-captured the full test run (9 tests,
1 clean skip), corrected README's test table, and closed a second,
unrelated gap: the unzip -l listing quoted in the @ServiceConnection section
had no matching captured transcript -- it does now.
This commit is contained in:
Claude
2026-10-08 12:35:04 +00:00
parent 97f946136b
commit 4370ac7fdf
9 changed files with 298 additions and 188 deletions
+18 -7
View File
@@ -6,9 +6,19 @@ Companion module for [`@DataJpaTest` with Testcontainers `@ServiceConnection` on
Six JUnit 5 test classes against one JPA repository (`Product`), each isolating one fact about 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 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 `@ServiceConnection` wires in its place, and what the defaults do run that you might not expect
not one of them). No `docs/NN-topic.md` chapters — everything beyond what fits in the post itself (Flyway migrations, as it turns out, are one of them). No `docs/NN-topic.md` chapters —
is in the Javadoc on these six test classes and in the captured transcripts below. everything beyond what fits in the post itself is in the Javadoc on these six test classes and in
the captured transcripts below.
**Correction, made before this module was published:** an earlier draft of two of these classes
asserted that `@DataJpaTest` never runs Flyway or Liquibase migrations, on the strength of reading
its four documented meta-annotations' `.imports` manifests and finding no mention of either tool.
That reading was accurate and incomplete — see `FlywayRunsByDefaultTest`'s Javadoc and
`docs/output/06-autoconfigurejdbc-meta-annotation-javap.txt` for the fifth, undocumented-for-this-slice
meta-annotation that actually wires them in. The two test classes below that carried the wrong
premise (`FlywayDoesNotRunUnderPlainDataJpaTestTest`, `FlywayRunsWhenExplicitlyImportedTest`) were
replaced, not patched, with `FlywayRunsByDefaultTest` and `ExplicitFlywayImportIsRedundantTest`.
**This module was built and tested in a sandbox with no Docker daemon available.** Five of the six **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 test classes run and pass (or cleanly skip) without one. The sixth demonstrates, on purpose, the
@@ -29,7 +39,7 @@ the test table below for exactly which is which.
## Quickstart ## Quickstart
```bash ```bash
mvn test # 6 of 7 run; 1 skips cleanly mvn test # 9 tests run; 1 skips cleanly
mvn test -Dtest=ServiceConnectionWithoutGuardFailsToStartTest # the one deliberate failure mvn test -Dtest=ServiceConnectionWithoutGuardFailsToStartTest # the one deliberate failure
``` ```
@@ -38,8 +48,8 @@ mvn test -Dtest=ServiceConnectionWithoutGuardFailsToStartTest # the one delibera
| Class | What it proves | Needs Docker | Outcome here | | 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 | | `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 | | `FlywayRunsByDefaultTest` | A plain `@DataJpaTest`, with flyway-core and `spring-boot-starter-flyway` on the (test) classpath, runs the real Flyway migration by default — no `@ImportAutoConfiguration` needed, because `@AutoConfigureJdbc` is itself meta-annotated with `@AutoConfigureDataSourceInitialization`, which merges contributions from every jar on the classpath that ships one | No | Pass |
| `FlywayRunsWhenExplicitlyImportedTest` | The one-line fix: `@ImportAutoConfiguration(FlywayAutoConfiguration.class)` | No | Pass | | `ExplicitFlywayImportIsRedundantTest` | Explicitly re-adding `@ImportAutoConfiguration(FlywayAutoConfiguration.class)` — the old advice for the (incorrect) premise above — changes nothing: still exactly one `flyway` bean, still exactly one applied migration | 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 | | `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 | | `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 | | `ServiceConnectionWithoutGuardFailsToStartTest` | The same class, minus the guard | Yes (unguarded) | **Fails — on purpose.** Excluded from `mvn test` by name in `pom.xml`; run it explicitly |
@@ -48,11 +58,12 @@ mvn test -Dtest=ServiceConnectionWithoutGuardFailsToStartTest # the one delibera
| File | Contents | | File | Contents |
|---|---| |---|---|
| `docs/output/00-full-test-run.txt` | `mvn clean test` — 7 tests, 1 skip, build green | | `docs/output/00-full-test-run.txt` | `mvn clean test` — 9 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/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/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/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 | | `docs/output/05-service-connection-skips-cleanly.txt` | The same absence of Docker, this time behind `@EnabledIfDockerAvailable` — one line, `Skipped: 1`, no failure |
| `docs/output/06-autoconfigurejdbc-meta-annotation-javap.txt` | `javap` proof that `AutoConfigureJdbc.class` is meta-annotated with `@AutoConfigureDataSourceInitialization`, plus the matching `META-INF/spring/...AutoConfigureDataSourceInitialization.imports` file contents from both `spring-boot-jdbc-test` and `spring-boot-flyway` — the actual mechanism behind `FlywayRunsByDefaultTest` |
## What's sourced from code, not run here ## What's sourced from code, not run here
@@ -36,10 +36,10 @@ WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release
[INFO] ------------------------------------------------------- [INFO] -------------------------------------------------------
Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts -Djavax.net.ssl.trustStoreType=JKS -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=34689 -Dhttp.nonProxyHosts=localhost|127.0.0.1|::1|127.*|0.*|::|169.254.*|api.anthropic.com|api-staging.anthropic.com|api-pr-preview.anthropic.com|mcp-proxy.anthropic.com|mcp-proxy-staging.anthropic.com|registry.npmjs.org|jsr.io|npm.jsr.io|pypi.org|files.pythonhosted.org|index.crates.io|proxy.golang.org|host.docker.internal|10.*|172.16.*|172.17.*|172.18.*|172.19.*|172.20.*|172.21.*|172.22.*|172.23.*|172.24.*|172.25.*|172.26.*|172.27.*|172.28.*|172.29.*|172.30.*|172.31.*|192.168.*|100.64.0.0/10|*.svc.cluster.local|*.svc.cluster.local -Djdk.http.auth.tunneling.disabledSchemes= -Djdk.http.auth.proxying.disabledSchemes= Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts -Djavax.net.ssl.trustStoreType=JKS -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=34689 -Dhttp.nonProxyHosts=localhost|127.0.0.1|::1|127.*|0.*|::|169.254.*|api.anthropic.com|api-staging.anthropic.com|api-pr-preview.anthropic.com|mcp-proxy.anthropic.com|mcp-proxy-staging.anthropic.com|registry.npmjs.org|jsr.io|npm.jsr.io|pypi.org|files.pythonhosted.org|index.crates.io|proxy.golang.org|host.docker.internal|10.*|172.16.*|172.17.*|172.18.*|172.19.*|172.20.*|172.21.*|172.22.*|172.23.*|172.24.*|172.25.*|172.26.*|172.27.*|172.28.*|172.29.*|172.30.*|172.31.*|192.168.*|100.64.0.0/10|*.svc.cluster.local|*.svc.cluster.local -Djdk.http.auth.tunneling.disabledSchemes= -Djdk.http.auth.proxying.disabledSchemes=
[INFO] Running com.ankurm.datajpa.DefaultReplacementTest [INFO] Running com.ankurm.datajpa.DefaultReplacementTest
17:19:49.092 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.ankurm.datajpa.DefaultReplacementTest]: DefaultReplacementTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 17:55:42.824 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.ankurm.datajpa.DefaultReplacementTest]: DefaultReplacementTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
17:19:49.365 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.DefaultReplacementTest 17:55:43.042 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.DefaultReplacementTest
17:19:49.370 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.ankurm.datajpa.DefaultReplacementTest]: DefaultReplacementTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 17:55:43.046 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.ankurm.datajpa.DefaultReplacementTest]: DefaultReplacementTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
17:19:49.405 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.DefaultReplacementTest 17:55:43.073 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.DefaultReplacementTest
. ____ _ __ _ _ . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
@@ -50,39 +50,39 @@ Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cace
:: Spring Boot :: (v4.1.1) :: Spring Boot :: (v4.1.1)
2026-10-08T17:19:50.032+05:30 INFO 2231 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : Starting DefaultReplacementTest using Java 25.0.4.1 with PID 2231 (started by root in /home/claude/spring-boot-demo/data-jpa-testcontainers) 2026-10-08T17:55:43.593+05:30 INFO 10940 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : Starting DefaultReplacementTest using Java 25.0.4.1 with PID 10940 (started by root in /home/claude/spring-boot-demo/data-jpa-testcontainers)
2026-10-08T17:19:50.034+05:30 INFO 2231 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : No active profile set, falling back to 1 default profile: "default" 2026-10-08T17:55:43.595+05:30 INFO 10940 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : No active profile set, falling back to 1 default profile: "default"
2026-10-08T17:19:50.614+05:30 INFO 2231 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2026-10-08T17:55:44.217+05:30 INFO 10940 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2026-10-08T17:19:50.751+05:30 INFO 2231 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 126 ms. Found 1 JPA repository interface. 2026-10-08T17:55:44.349+05:30 INFO 10940 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 118 ms. Found 1 JPA repository interface.
2026-10-08T17:19:50.849+05:30 INFO 2231 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version 2026-10-08T17:55:44.495+05:30 INFO 10940 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version
2026-10-08T17:19:51.122+05:30 INFO 2231 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:27737b58-793d-4017-ae78-1a78ebfc5b27;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa' 2026-10-08T17:55:44.784+05:30 INFO 10940 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:4440be02-551f-486e-a4b1-2182bb84c7a5;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
2026-10-08T17:19:51.815+05:30 INFO 2231 --- [ main] org.flywaydb.core.FlywayExecutor : Database: jdbc:h2:mem:27737b58-793d-4017-ae78-1a78ebfc5b27 (H2 2.4) 2026-10-08T17:55:45.448+05:30 INFO 10940 --- [ main] org.flywaydb.core.FlywayExecutor : Database: jdbc:h2:mem:4440be02-551f-486e-a4b1-2182bb84c7a5 (H2 2.4)
2026-10-08T17:19:51.888+05:30 WARN 2231 --- [ main] o.f.c.internal.database.base.Database : Using H2 2.4.240 which is newer than the version Flyway has been verified with. The latest verified version of H2 is 2.3.232. 2026-10-08T17:55:45.514+05:30 WARN 10940 --- [ main] o.f.c.internal.database.base.Database : Using H2 2.4.240 which is newer than the version Flyway has been verified with. The latest verified version of H2 is 2.3.232.
2026-10-08T17:19:51.949+05:30 INFO 2231 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Schema history table "PUBLIC"."flyway_schema_history" does not exist yet 2026-10-08T17:55:45.551+05:30 INFO 10940 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Schema history table "PUBLIC"."flyway_schema_history" does not exist yet
2026-10-08T17:19:51.952+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.040s) 2026-10-08T17:55:45.555+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.014s)
2026-10-08T17:19:51.960+05:30 INFO 2231 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table "PUBLIC"."flyway_schema_history" ... 2026-10-08T17:55:45.582+05:30 INFO 10940 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table "PUBLIC"."flyway_schema_history" ...
2026-10-08T17:19:52.002+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >> 2026-10-08T17:55:45.640+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >>
2026-10-08T17:19:52.015+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version "1 - create product" 2026-10-08T17:55:45.652+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version "1 - create product"
2026-10-08T17:19:52.034+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC", now at version v1 (execution time 00:00.008s) 2026-10-08T17:55:45.750+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC", now at version v1 (execution time 00:00.016s)
2026-10-08T17:19:52.268+05:30 INFO 2231 --- [ main] org.hibernate.orm.jpa : HHH008540: Processing PersistenceUnitInfo [name: default] 2026-10-08T17:55:46.001+05:30 INFO 10940 --- [ main] org.hibernate.orm.jpa : HHH008540: Processing PersistenceUnitInfo [name: default]
2026-10-08T17:19:52.332+05:30 INFO 2231 --- [ main] org.hibernate.orm.core : HHH000001: Hibernate ORM core version 7.4.5.Final 2026-10-08T17:55:46.079+05:30 INFO 10940 --- [ main] org.hibernate.orm.core : HHH000001: Hibernate ORM core version 7.4.5.Final
2026-10-08T17:19:52.886+05:30 INFO 2231 --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer 2026-10-08T17:55:46.707+05:30 INFO 10940 --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer
2026-10-08T17:19:53.006+05:30 INFO 2231 --- [ main] org.hibernate.orm.connections.pooling : HHH10001005: Database info: 2026-10-08T17:55:46.832+05:30 INFO 10940 --- [ main] org.hibernate.orm.connections.pooling : HHH10001005: Database info:
Database JDBC URL [jdbc:h2:mem:27737b58-793d-4017-ae78-1a78ebfc5b27] Database JDBC URL [jdbc:h2:mem:4440be02-551f-486e-a4b1-2182bb84c7a5]
Database driver: H2 JDBC Driver Database driver: H2 JDBC Driver
Database dialect: H2Dialect Database dialect: H2Dialect
Database version: 2.4.240 Database version: 2.4.240
Default catalog/schema: 27737B58-793D-4017-AE78-1A78EBFC5B27/PUBLIC Default catalog/schema: 4440BE02-551F-486E-A4B1-2182BB84C7A5/PUBLIC
Autocommit mode: undefined/unknown Autocommit mode: undefined/unknown
Isolation level: READ_COMMITTED [default READ_COMMITTED] Isolation level: READ_COMMITTED [default READ_COMMITTED]
JDBC fetch size: 100 JDBC fetch size: 100
Pool: DataSourceConnectionProvider Pool: DataSourceConnectionProvider
Minimum pool size: undefined/unknown Minimum pool size: undefined/unknown
Maximum pool size: undefined/unknown Maximum pool size: undefined/unknown
2026-10-08T17:19:54.129+05:30 INFO 2231 --- [ main] org.hibernate.orm.core : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) 2026-10-08T17:55:47.973+05:30 INFO 10940 --- [ main] org.hibernate.orm.core : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2026-10-08T17:19:54.145+05:30 INFO 2231 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2026-10-08T17:55:47.989+05:30 INFO 10940 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-10-08T17:19:54.332+05:30 INFO 2231 --- [ main] o.s.d.j.r.query.QueryEnhancerFactories : Hibernate is in classpath; If applicable, HQL parser will be used. 2026-10-08T17:55:48.156+05:30 INFO 10940 --- [ main] o.s.d.j.r.query.QueryEnhancerFactories : Hibernate is in classpath; If applicable, HQL parser will be used.
2026-10-08T17:19:54.604+05:30 INFO 2231 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : Started DefaultReplacementTest in 5.076 seconds (process running for 7.153) 2026-10-08T17:55:48.476+05:30 INFO 10940 --- [ main] c.ankurm.datajpa.DefaultReplacementTest : Started DefaultReplacementTest in 5.325 seconds (process running for 7.158)
Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3 Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
WARNING: A Java agent has been loaded dynamically (/root/.m2/repository/net/bytebuddy/byte-buddy-agent/1.18.11/byte-buddy-agent-1.18.11.jar) WARNING: A Java agent has been loaded dynamically (/root/.m2/repository/net/bytebuddy/byte-buddy-agent/1.18.11/byte-buddy-agent-1.18.11.jar)
@@ -95,12 +95,12 @@ JDBC reports database product name: H2
Hibernate: insert into product (name,sku,id) values (?,?,default) Hibernate: insert into product (name,sku,id) values (?,?,default)
Hibernate: select p1_0.id,p1_0.name,p1_0.sku from product p1_0 where p1_0.sku=? Hibernate: select p1_0.id,p1_0.name,p1_0.sku from product p1_0 where p1_0.sku=?
Hibernate: select count(*) from product p1_0 Hibernate: select count(*) from product p1_0
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.329 s -- in com.ankurm.datajpa.DefaultReplacementTest [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.500 s -- in com.ankurm.datajpa.DefaultReplacementTest
[INFO] Running com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test [INFO] Running com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test
2026-10-08T17:19:56.108+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test]: NoSubstitutionStillSilentlyUsesH2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2026-10-08T17:55:50.002+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test]: NoSubstitutionStillSilentlyUsesH2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:19:56.189+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test 2026-10-08T17:55:50.040+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test
2026-10-08T17:19:56.197+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test]: NoSubstitutionStillSilentlyUsesH2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2026-10-08T17:55:50.041+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test]: NoSubstitutionStillSilentlyUsesH2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:19:56.238+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test 2026-10-08T17:55:50.069+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test
. ____ _ __ _ _ . ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
@@ -111,74 +111,75 @@ Hibernate: select count(*) from product p1_0
:: Spring Boot :: (v4.1.1) :: Spring Boot :: (v4.1.1)
2026-10-08T17:19:56.294+05:30 INFO 2231 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : Starting NoSubstitutionStillSilentlyUsesH2Test using Java 25.0.4.1 with PID 2231 (started by root in /home/claude/spring-boot-demo/data-jpa-testcontainers) 2026-10-08T17:55:50.166+05:30 INFO 10940 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : Starting NoSubstitutionStillSilentlyUsesH2Test using Java 25.0.4.1 with PID 10940 (started by root in /home/claude/spring-boot-demo/data-jpa-testcontainers)
2026-10-08T17:19:56.295+05:30 INFO 2231 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : No active profile set, falling back to 1 default profile: "default" 2026-10-08T17:55:50.167+05:30 INFO 10940 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : No active profile set, falling back to 1 default profile: "default"
2026-10-08T17:19:56.452+05:30 INFO 2231 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2026-10-08T17:55:50.366+05:30 INFO 10940 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2026-10-08T17:19:56.469+05:30 INFO 2231 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 13 ms. Found 1 JPA repository interface. 2026-10-08T17:55:50.381+05:30 INFO 10940 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 12 ms. Found 1 JPA repository interface.
2026-10-08T17:19:56.642+05:30 INFO 2231 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2026-10-08T17:55:50.538+05:30 INFO 10940 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2026-10-08T17:19:56.665+05:30 INFO 2231 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn9: url=jdbc:h2:mem:fb5a3fcb-6cc0-4a37-baff-7dbd0bfb51fd user=SA 2026-10-08T17:55:50.563+05:30 INFO 10940 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn9: url=jdbc:h2:mem:59a60d3a-9329-4255-85ca-9683b850ef31 user=SA
2026-10-08T17:19:56.667+05:30 INFO 2231 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2026-10-08T17:55:50.566+05:30 INFO 10940 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2026-10-08T17:19:56.673+05:30 INFO 2231 --- [ main] org.flywaydb.core.FlywayExecutor : Database: jdbc:h2:mem:fb5a3fcb-6cc0-4a37-baff-7dbd0bfb51fd (H2 2.4) 2026-10-08T17:55:50.573+05:30 INFO 10940 --- [ main] org.flywaydb.core.FlywayExecutor : Database: jdbc:h2:mem:59a60d3a-9329-4255-85ca-9683b850ef31 (H2 2.4)
2026-10-08T17:19:56.686+05:30 WARN 2231 --- [ main] o.f.c.internal.database.base.Database : Using H2 2.4.240 which is newer than the version Flyway has been verified with. The latest verified version of H2 is 2.3.232. 2026-10-08T17:55:50.597+05:30 WARN 10940 --- [ main] o.f.c.internal.database.base.Database : Using H2 2.4.240 which is newer than the version Flyway has been verified with. The latest verified version of H2 is 2.3.232.
2026-10-08T17:19:56.690+05:30 INFO 2231 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Schema history table "PUBLIC"."flyway_schema_history" does not exist yet 2026-10-08T17:55:50.607+05:30 INFO 10940 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Schema history table "PUBLIC"."flyway_schema_history" does not exist yet
2026-10-08T17:19:56.691+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.002s) 2026-10-08T17:55:50.608+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.005s)
2026-10-08T17:19:56.693+05:30 INFO 2231 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table "PUBLIC"."flyway_schema_history" ... 2026-10-08T17:55:50.610+05:30 INFO 10940 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table "PUBLIC"."flyway_schema_history" ...
2026-10-08T17:19:56.703+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >> 2026-10-08T17:55:50.723+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >>
2026-10-08T17:19:56.707+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version "1 - create product" 2026-10-08T17:55:50.735+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version "1 - create product"
2026-10-08T17:19:56.715+05:30 INFO 2231 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC", now at version v1 (execution time 00:00.004s) 2026-10-08T17:55:50.745+05:30 INFO 10940 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC", now at version v1 (execution time 00:00.006s)
2026-10-08T17:19:56.752+05:30 INFO 2231 --- [ main] org.hibernate.orm.jpa : HHH008540: Processing PersistenceUnitInfo [name: default] 2026-10-08T17:55:50.829+05:30 INFO 10940 --- [ main] org.hibernate.orm.jpa : HHH008540: Processing PersistenceUnitInfo [name: default]
2026-10-08T17:19:56.808+05:30 INFO 2231 --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer 2026-10-08T17:55:50.897+05:30 INFO 10940 --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer
2026-10-08T17:19:56.814+05:30 INFO 2231 --- [ main] org.hibernate.orm.connections.pooling : HHH10001005: Database info: 2026-10-08T17:55:50.902+05:30 INFO 10940 --- [ main] org.hibernate.orm.connections.pooling : HHH10001005: Database info:
Database JDBC URL [jdbc:h2:mem:fb5a3fcb-6cc0-4a37-baff-7dbd0bfb51fd] Database JDBC URL [jdbc:h2:mem:59a60d3a-9329-4255-85ca-9683b850ef31]
Database driver: H2 JDBC Driver Database driver: H2 JDBC Driver
Database dialect: H2Dialect Database dialect: H2Dialect
Database version: 2.4.240 Database version: 2.4.240
Default catalog/schema: FB5A3FCB-6CC0-4A37-BAFF-7DBD0BFB51FD/PUBLIC Default catalog/schema: 59A60D3A-9329-4255-85CA-9683B850EF31/PUBLIC
Autocommit mode: undefined/unknown Autocommit mode: undefined/unknown
Isolation level: READ_COMMITTED [default READ_COMMITTED] Isolation level: READ_COMMITTED [default READ_COMMITTED]
JDBC fetch size: 100 JDBC fetch size: 100
Pool: DataSourceConnectionProvider Pool: DataSourceConnectionProvider
Minimum pool size: undefined/unknown Minimum pool size: undefined/unknown
Maximum pool size: undefined/unknown Maximum pool size: undefined/unknown
2026-10-08T17:19:56.850+05:30 INFO 2231 --- [ main] org.hibernate.orm.core : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) 2026-10-08T17:55:50.956+05:30 INFO 10940 --- [ main] org.hibernate.orm.core : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2026-10-08T17:19:56.851+05:30 INFO 2231 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2026-10-08T17:55:50.958+05:30 INFO 10940 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-10-08T17:19:56.915+05:30 INFO 2231 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : Started NoSubstitutionStillSilentlyUsesH2Test in 0.668 seconds (process running for 9.464) 2026-10-08T17:55:51.035+05:30 INFO 10940 --- [ main] .d.NoSubstitutionStillSilentlyUsesH2Test : Started NoSubstitutionStillSilentlyUsesH2Test in 0.949 seconds (process running for 9.717)
JDBC reports database product name: H2 (even with replace = Replace.NONE and no @ServiceConnection anywhere) JDBC reports database product name: H2 (even with replace = Replace.NONE and no @ServiceConnection anywhere)
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.852 s -- in com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.083 s -- in com.ankurm.datajpa.NoSubstitutionStillSilentlyUsesH2Test
[INFO] Running com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest [INFO] Running com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest
2026-10-08T17:19:56.952+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest]: FlywayDoesNotRunUnderPlainDataJpaTestTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2026-10-08T17:55:51.081+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest]: ExplicitFlywayImportIsRedundantTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:19:57.008+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest 2026-10-08T17:55:51.135+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest
2026-10-08T17:19:57.008+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest]: FlywayDoesNotRunUnderPlainDataJpaTestTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2026-10-08T17:55:51.139+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest]: ExplicitFlywayImportIsRedundantTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:19:57.064+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest 2026-10-08T17:55:51.195+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.137 s -- in com.ankurm.datajpa.FlywayDoesNotRunUnderPlainDataJpaTestTest flyway_schema_history real migration rows (rank >= 0): 1
[INFO] Running com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.226 s -- in com.ankurm.datajpa.ExplicitFlywayImportIsRedundantTest
2026-10-08T17:19:57.091+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest]: FlywayRunsWhenExplicitlyImportedTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2026-10-08T17:55:51.324+05:30 INFO 10940 --- [ main] org.testcontainers.DockerClientFactory : Testcontainers version: 2.0.5
2026-10-08T17:19:57.107+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest
2026-10-08T17:19:57.107+05:30 INFO 2231 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest]: FlywayRunsWhenExplicitlyImportedTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:19:57.132+05:30 INFO 2231 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest
flyway_schema_history row: version=1 description=create product success=true
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.085 s -- in com.ankurm.datajpa.FlywayRunsWhenExplicitlyImportedTest
2026-10-08T17:19:57.218+05:30 INFO 2231 --- [ main] org.testcontainers.DockerClientFactory : Testcontainers version: 2.0.5
WARNING: A restricted method in java.lang.System has been called WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by com.sun.jna.Native in an unnamed module (file:/root/.m2/repository/net/java/dev/jna/jna/5.18.1/jna-5.18.1.jar) WARNING: java.lang.System::load has been called by com.sun.jna.Native in an unnamed module (file:/root/.m2/repository/net/java/dev/jna/jna/5.18.1/jna-5.18.1.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled WARNING: Restricted methods will be blocked in a future release unless native access is enabled
2026-10-08T17:19:57.537+05:30 INFO 2231 --- [ main] .t.d.DockerMachineClientProviderStrategy : docker-machine executable was not found on PATH ([/opt/jdk-25/bin, /home/claude/.npm-global/bin, /nix/var/nix/profiles/default/bin, /root/.local/bin, /root/.cargo/bin, /usr/local/go/bin, /opt/node22/bin, /opt/maven/bin, /opt/gradle/bin, /opt/rbenv/bin, /root/.bun/bin, /usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin]) 2026-10-08T17:55:51.689+05:30 INFO 10940 --- [ main] .t.d.DockerMachineClientProviderStrategy : docker-machine executable was not found on PATH ([/opt/jdk-25/bin, /home/claude/.npm-global/bin, /nix/var/nix/profiles/default/bin, /root/.local/bin, /root/.cargo/bin, /usr/local/go/bin, /opt/node22/bin, /opt/maven/bin, /opt/gradle/bin, /opt/rbenv/bin, /root/.bun/bin, /usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin])
2026-10-08T17:19:57.538+05:30 ERROR 2231 --- [ main] o.t.d.DockerClientProviderStrategy : Could not find a valid Docker environment. Please check configuration. Attempted configurations were: 2026-10-08T17:55:51.691+05:30 ERROR 10940 --- [ main] o.t.d.DockerClientProviderStrategy : Could not find a valid Docker environment. Please check configuration. Attempted configurations were:
UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock) UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (Could not find unix domain socket). Root cause NoSuchFileException (/var/run/docker.sock)
DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue. DockerDesktopClientProviderStrategy: failed with exception NullPointerException (Cannot invoke "java.nio.file.Path.toString()" because the return value of "org.testcontainers.dockerclient.DockerDesktopClientProviderStrategy.getSocketPath()" is null)As no valid configuration was found, execution cannot continue.
See https://java.testcontainers.org/on_failure.html for more details. See https://java.testcontainers.org/on_failure.html for more details.
[INFO] Running com.ankurm.datajpa.ServiceConnectionSkipsCleanlyTest [INFO] Running com.ankurm.datajpa.ServiceConnectionSkipsCleanlyTest
[WARNING] Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.001 s -- in com.ankurm.datajpa.ServiceConnectionSkipsCleanlyTest [WARNING] Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.009 s -- in com.ankurm.datajpa.ServiceConnectionSkipsCleanlyTest
[INFO] Running com.ankurm.datajpa.FlywayRunsByDefaultTest
2026-10-08T17:55:51.702+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayRunsByDefaultTest]: FlywayRunsByDefaultTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:55:51.716+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayRunsByDefaultTest
2026-10-08T17:55:51.717+05:30 INFO 10940 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [com.ankurm.datajpa.FlywayRunsByDefaultTest]: FlywayRunsByDefaultTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2026-10-08T17:55:51.731+05:30 INFO 10940 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration com.ankurm.datajpa.DataJpaTestcontainersApplication for test class com.ankurm.datajpa.FlywayRunsByDefaultTest
flyway_schema_history row: version=1 description=create product success=true
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.079 s -- in com.ankurm.datajpa.FlywayRunsByDefaultTest
[INFO] [INFO]
[INFO] Results: [INFO] Results:
[INFO] [INFO]
[INFO] Tests run: 7, Failures: 0, Errors: 0, Skipped: 1 [INFO] Tests run: 9, Failures: 0, Errors: 0, Skipped: 1
[INFO] [INFO]
[INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS [INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------
[INFO] Total time: 15.580 s [INFO] Total time: 14.464 s
[INFO] Finished at: 2026-10-08T17:19:57+05:30 [INFO] Finished at: 2026-10-08T17:55:51+05:30
[INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------
@@ -75,3 +75,8 @@ $ javap -v org/testcontainers/containers/PostgreSQLContainer.class | grep -i dep
Deprecated: true Deprecated: true
java.lang.Deprecated java.lang.Deprecated
Deprecated: true Deprecated: true
$ unzip -l /root/.m2/repository/org/testcontainers/testcontainers-postgresql/2.0.5/testcontainers-postgresql-2.0.5.jar | grep PostgreSQLContainer
5533 2026-04-06 22:36 org/testcontainers/postgresql/PostgreSQLContainer.class
1745 2026-04-06 22:36 org/testcontainers/containers/PostgreSQLContainerProvider.class
6150 2026-04-06 22:36 org/testcontainers/containers/PostgreSQLContainer.class
@@ -0,0 +1,40 @@
$ javap -v org/springframework/boot/jdbc/test/autoconfigure/AutoConfigureJdbc.class
# unzipped from spring-boot-jdbc-test-4.1.1.jar
RuntimeVisibleAnnotations:
0: #10(#11=[e#12.#13])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
)
1: #14(#11=e#15.#16)
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.RUNTIME
)
2: #17()
java.lang.annotation.Documented
3: #18()
java.lang.annotation.Inherited
4: #19()
org.springframework.boot.autoconfigure.ImportAutoConfiguration
5: #20()
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureDataSourceInitialization
$ find . -iname '*DataSourceInitialization*' # inside spring-boot-jdbc-test-4.1.1.jar
./META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureDataSourceInitialization.imports
$ cat META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureDataSourceInitialization.imports
org.springframework.boot.jdbc.autoconfigure.DataSourceInitializationAutoConfiguration
# the SAME resource path, inside spring-boot-flyway-4.1.1.jar instead:
$ cat META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureDataSourceInitialization.imports
org.springframework.boot.flyway.autoconfigure.FlywayAutoConfiguration
$ javap -v org/springframework/boot/flyway/autoconfigure/FlywayAutoConfiguration.class # unzipped from spring-boot-flyway-4.1.1.jar
#41 = Utf8 Lorg/springframework/boot/autoconfigure/condition/ConditionalOnClass;
#42 = Utf8 value
#43 = Utf8 Lorg/flywaydb/core/Flyway;
#44 = Utf8 Lorg/springframework/context/annotation/Conditional;
--
org.springframework.boot.autoconfigure.condition.ConditionalOnClass(
value=[class Lorg/flywaydb/core/Flyway;]
)
2: #44(#42=[c#45])
+6 -3
View File
@@ -47,9 +47,12 @@
<!-- flyway-core on the classpath is NOT enough to get FlywayAutoConfiguration — that class <!-- flyway-core on the classpath is NOT enough to get FlywayAutoConfiguration — that class
lives in its own starter, a further instance of Boot 4's per-technology module split lives in its own starter, a further instance of Boot 4's per-technology module split
(confirmed by comparing against the db-migrations-flyway-liquibase module, which needs the (confirmed by comparing against the db-migrations-flyway-liquibase module, which needs the
exact same starter). Test scope only: this article's main app never runs Flyway itself, the exact same starter). This is what actually makes Flyway run under @DataJpaTest by default
two test classes that explicitly re-import FlywayAutoConfiguration are what need the class in this module: @AutoConfigureJdbc's @AutoConfigureDataSourceInitialization meta-annotation
on the classpath at all. --> merges a META-INF/spring/...AutoConfigureDataSourceInitialization.imports file from every
jar that ships one, and spring-boot-flyway (pulled in by this starter) is one of them —
confirmed with javap and unzip, see FlywayRunsByDefaultTest's Javadoc. Test scope only:
this article's main app never runs Flyway itself outside the test slice. -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId> <artifactId>spring-boot-starter-flyway</artifactId>
@@ -0,0 +1,59 @@
package com.ankurm.datajpa;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.boot.flyway.autoconfigure.FlywayAutoConfiguration;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Older advice for this exact situation (including an earlier draft of this module, and more
* than one blog post this article will not link to) says to add
* {@code @ImportAutoConfiguration(FlywayAutoConfiguration.class)} yourself to get Flyway running
* inside a {@code @DataJpaTest}. As {@link FlywayRunsByDefaultTest} now shows, that is no longer
* necessary on Spring Boot 4.1 -- the import already happens on its own, by way of
* {@code @AutoConfigureJdbc}'s own {@code @AutoConfigureDataSourceInitialization} meta-annotation.
*
* <p>Adding the explicit import anyway is not harmful. {@code @ImportAutoConfiguration} is
* backed by ordinary Spring auto-configuration machinery: the same fully-qualified class name,
* however many times it is reached (once through the transitive meta-annotation walk, once
* through this class's own explicit annotation), is only ever registered once. This test proves
* that directly rather than asserting it from the mechanism alone: exactly one {@code flyway}
* bean, and exactly one applied migration -- not two -- with the redundant import sitting right
* there on the class.
*/
@DataJpaTest
@ImportAutoConfiguration(FlywayAutoConfiguration.class)
class ExplicitFlywayImportIsRedundantTest {
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext ctx;
@Test
void redundantImportStillProducesExactlyOneFlywayBean() {
assertThat(ctx.getBeanNamesForType(org.flywaydb.core.Flyway.class)).hasSize(1);
}
@Test
void redundantImportDoesNotReapplyTheMigration() throws Exception {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
var rs = statement.executeQuery(
"select count(*) from \"flyway_schema_history\" where \"installed_rank\" >= 0");
assertThat(rs.next()).isTrue();
int realMigrationRows = rs.getInt(1);
System.out.println("flyway_schema_history real migration rows (rank >= 0): " + realMigrationRows);
assertThat(realMigrationRows).isEqualTo(1);
}
}
}
@@ -1,49 +0,0 @@
package com.ankurm.datajpa;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import static org.assertj.core.api.Assertions.assertThat;
/**
* This module has a real Flyway migration, {@code V1__create_product.sql}, and flyway-core is a
* main-scope dependency. A plain @DataJpaTest never runs it anyway -- not because of the
* embedded-database substitution, but because @DataJpaTest's own curated set of auto-configuration
* imports simply does not include FlywayAutoConfiguration or LiquibaseAutoConfiguration at all.
* Confirmed by reading the actual import manifests Boot ships inside spring-boot-jdbc-test.jar and
* spring-boot-data-jpa-test.jar -- neither file mentions Flyway or Liquibase, in any form, under
* any replace setting.
*
* The {@code product} table exists in this test for a completely different reason: Hibernate's own
* {@code ddl-auto}, defaulted on because Boot never detects a schema-management tool in this
* slice's context. See {@link FlywayRunsWhenExplicitlyImportedTest} for the one-line fix.
*/
@DataJpaTest
class FlywayDoesNotRunUnderPlainDataJpaTestTest {
@Autowired
private DataSource dataSource;
@Test
void productTableExistsButFlywayNeverRan() throws Exception {
try (Connection connection = dataSource.getConnection()) {
try (ResultSet flywayTable = connection.getMetaData()
.getTables(null, null, "FLYWAY_SCHEMA_HISTORY", null)) {
assertThat(flywayTable.next())
.as("flyway_schema_history should not exist -- Flyway never ran")
.isFalse();
}
try (ResultSet productTable = connection.getMetaData()
.getTables(null, null, "PRODUCT", null)) {
assertThat(productTable.next())
.as("product table should exist anyway -- Hibernate's ddl-auto made it")
.isTrue();
}
}
}
}
@@ -0,0 +1,92 @@
package com.ankurm.datajpa;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import static org.assertj.core.api.Assertions.assertThat;
/**
* This module has a real Flyway migration, {@code V1__create_product.sql}, and flyway-core
* (plus the test-scoped {@code spring-boot-starter-flyway} -- see the module README for why that
* second one matters) is on the classpath. A plain {@code @DataJpaTest}, with no extra
* annotation anywhere on this class, runs that migration by default.
*
* <p>An earlier draft of this module asserted the opposite, on the strength of reading
* {@code @DataJpaTest}'s four documented meta-annotations ({@code @AutoConfigureDataJpa},
* {@code @AutoConfigureJdbc}, {@code @AutoConfigureTestDatabase},
* {@code @AutoConfigureTestEntityManager}) and finding that none of their four
* {@code .imports} manifests mentions Flyway or Liquibase. That reading is correct and
* incomplete: {@code AutoConfigureJdbc.class} is itself meta-annotated with a fifth annotation,
* {@code @AutoConfigureDataSourceInitialization} (new in Boot 4.0; confirmed with
* {@code javap -v org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureJdbc} against
* {@code spring-boot-jdbc-test-4.1.1.jar}), and Spring's own
* {@code ImportAutoConfigurationImportSelector} walks the entire meta-annotation tree
* transitively -- every annotation, and every meta-annotation on those -- collecting every class
* in that tree that is itself annotated with {@code @ImportAutoConfiguration}. That fifth
* annotation is one of them.
*
* <p>{@code @AutoConfigureDataSourceInitialization}'s own {@code .imports} resource is loaded via
* {@code ClassLoader.getResources()}, which returns every file at that path across every jar on
* the classpath and merges them -- not a single-file lookup. Three jars ship a file at the exact
* same resource path
* ({@code META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureDataSourceInitialization.imports}):
* {@code spring-boot-jdbc-test} contributes {@code DataSourceInitializationAutoConfiguration},
* {@code spring-boot-flyway} contributes {@code FlywayAutoConfiguration}, and
* {@code spring-boot-liquibase} contributes {@code LiquibaseAutoConfiguration}. Confirmed by
* unzipping both jars actually on this classpath and reading the file; the Liquibase side was
* not independently re-run here (no Liquibase module in this repo) but the same mechanism applies
* to it by construction. {@code FlywayAutoConfiguration} is still gated by the ordinary
* {@code @ConditionalOnClass(Flyway.class)} -- it only activates once flyway-core is genuinely on
* the classpath, which is the one part of the old draft's observation that was never wrong, just
* misattributed to the wrong mechanism.
*
* <p>See {@link ExplicitFlywayImportIsRedundantTest} for what this means for the (now
* unnecessary, but harmless) advice to {@code @ImportAutoConfiguration(FlywayAutoConfiguration.class)}
* yourself.
*/
@DataJpaTest
class FlywayRunsByDefaultTest {
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext ctx;
@Test
void flywayAutoConfigurationBeansArePresentWithNoExplicitImportAnywhere() {
assertThat(ctx.getBeanNamesForType(org.flywaydb.core.Flyway.class)).isNotEmpty();
assertThat(ctx.containsBean("flywayInitializer")).isTrue();
}
@Test
void theMigrationActuallyRanAgainstTheSubstitutedDatabase() throws Exception {
// Flyway's own history table always carries a bookkeeping row at installed_rank = -1
// ("<< Flyway Schema History table created >>") ahead of the real migration rows, and
// both the table name and every column name are stored quoted and lowercase -- H2's
// default unquoted-identifier folding (to uppercase) does not apply to any of them.
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(
"select \"installed_rank\", \"version\", \"description\", \"success\" "
+ "from \"flyway_schema_history\" where \"installed_rank\" = 1")) {
assertThat(rs.next()).isTrue();
String version = rs.getString(2);
String description = rs.getString(3);
boolean success = rs.getBoolean(4);
System.out.println("flyway_schema_history row: version=" + version
+ " description=" + description + " success=" + success);
assertThat(version).isEqualTo("1");
assertThat(description).isEqualTo("create product");
assertThat(success).isTrue();
assertThat(rs.next()).isFalse();
}
}
}
@@ -1,52 +0,0 @@
package com.ankurm.datajpa;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.boot.flyway.autoconfigure.FlywayAutoConfiguration;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import static org.assertj.core.api.Assertions.assertThat;
/**
* The one-line fix for {@link FlywayDoesNotRunUnderPlainDataJpaTestTest}: pull
* FlywayAutoConfiguration into the slice yourself. Once it is in the context, Boot's own
* schema-management detection sees it, flips Hibernate's ddl-auto back to {@code none}, and the
* real migration runs against the same substituted (here, H2) DataSource.
*/
@DataJpaTest
@ImportAutoConfiguration(FlywayAutoConfiguration.class)
class FlywayRunsWhenExplicitlyImportedTest {
@Autowired
private DataSource dataSource;
@Test
void flywayHistoryTableProvesTheMigrationRanThisTime() throws Exception {
// Flyway's own history table always carries a bookkeeping row at installed_rank = -1
// ("<< Flyway Schema History table created >>") ahead of the real migration rows --
// easy to miss if a query only reads the first row back, which is what an earlier draft
// of this test did. The real V1 migration is installed_rank = 1.
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(
"select \"installed_rank\", \"version\", \"description\", \"success\" "
+ "from \"flyway_schema_history\" where \"installed_rank\" = 1")) {
assertThat(rs.next()).isTrue();
String version = rs.getString(2);
String description = rs.getString(3);
boolean success = rs.getBoolean(4);
System.out.println("flyway_schema_history row: version=" + version
+ " description=" + description + " success=" + success);
assertThat(version).isEqualTo("1");
assertThat(description).isEqualTo("create product");
assertThat(success).isTrue();
assertThat(rs.next()).isFalse();
}
}
}