The core problem: a Testcontainer's connection details (URL, port, credentials) aren't known until the container starts at runtime, but Spring resolves @Value/properties when the context builds. @DynamicPropertySource and @ServiceConnection are the two bridges that feed runtime container values into the Spring Environment.
@DynamicPropertySource — the general bridge
A static method annotated @DynamicPropertySource receives a DynamicPropertyRegistry. It runs after the container starts but before the context's properties are finalized, so you can register property suppliers that pull live values from the container:
@SpringBootTest
@Testcontainers
class OrderRepositoryIT {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16");
@DynamicPropertySource
static void props(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
}
Two details matter. The method must be static (it runs before any instance exists), and you register suppliers (method references / lambdas), not plain values — they're evaluated lazily, after the container is up. This works for anything: a Kafka container's bootstrap servers, a Redis host/port, a custom service's URL.
@ServiceConnection — the modern shortcut (Boot 3.1+)
For supported container types, Spring Boot 3.1 added @ServiceConnection, which eliminates the boilerplate entirely. Annotate the container and Boot detects its type (Postgres, Kafka, Redis, MongoDB, RabbitMQ, …) and auto-registers the right connection properties via a ConnectionDetails bean — no manual property names to get wrong.
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");
// No @DynamicPropertySource needed — URL/user/password wired automatically.
Which to use
@ServiceConnection— first choice whenever the container type is supported. Less code, no chance of a typo'd property key, and it sets the right keys for that technology.@DynamicPropertySource— the fallback for unsupported containers, custom services, or when you need to compute a non-standard property (e.g. a constructed URL with extra params).