@ServiceConnection supplies connection details, but a test-scoped container can stop while a cached Spring context still points to it.
Spring Boot Testcontainers: service connections and cached-context lifecycle
Connection details win over a hand-built URL
Spring Boot can inspect a Testcontainers container marked @ServiceConnection and supply the matching connection details to auto-configuration. That removes hard-coded random ports from a repository test. The container must still be in the test classpath and supported by the relevant Spring Boot integration. If several data sources exist, qualify which connection is under test instead of hoping a generic container bean selects the right one.
Align two lifetimes
A static JUnit container managed by the Testcontainers extension can stop after its test class. Spring's test context cache may retain an ApplicationContext that points to that stopped database for a later class. Put the container under Spring context management when sharing the context, or deliberately avoid context reuse; do not solve a lifecycle mismatch by adding sleeps. Context tests and process-boundary tests have different costs.
Prove reuse across classes
Run two test classes sequentially with the same cached context. Assert both can query the database and that the mapped port remains valid. Then run them in parallel if CI does so. The bean sketch states ownership by Spring; dependency coordinates, image policy and test database migrations remain project-specific.
Implementation sketch
@TestConfiguration(proxyBeanMethods = false)
class InventoryDatabaseTestConfig {
@Bean
@ServiceConnection
PostgreSQLContainer<?> inventoryDatabase() {
return new PostgreSQLContainer<>("postgres:16-alpine");
}
}Cost and verification
Starting a real database container is slower than a mocked repository, but it checks driver, schema and transaction behavior. Context reuse saves startup time only when the container lifetime matches it.
Common Mistakes
- Do not assume @ServiceConnection proves migrations or application queries work.
- Do not let a JUnit-scoped container stop before a reused Spring context.
- Do not replace database integration tests with an in-memory dialect when SQL behavior matters.
Read next
Spring ApplicationContextRunner: check conditional assembly in isolation, Spring tests: separate business rules, wiring and transport, Spring Boot config tests: what a child JVM proves and what deployment still owes, Spring Kafka testing layers: know what a direct listener test cannot prove.
Related boundary
Spring Boot Testcontainers and Flyway: let one owner prepare the test schema
