ServiceConnectionContextCustomizerFactory looks for fields annotated with @ServiceConnection in the test class and test's parent classes.
As far as I could figure out, the only way to re-use @ServiceConnection annotated containers between tests is creating a base class with test containers declaration:
public abstract class IntegrationTest {
@JdbcServiceConnection
static PostgreSQLContainer postgres = new PostgreSQLContainer(DockerImageName.parse("postgres:15.1"));
// alternatively @Testcontainers & @Container annotations from `junit-jupiter` can be used
static {
postgres.start();
}
}
@SpringBootTest
class AppServiceConnectionStaticBaseClassTests extends IntegrationTest {
@Test
void contextLoads() {
}
}
Spring, generally speaking supports test configuration composition through annotations or interfaces. I believe it would be nice if @ServiceConnection could be used in the same way. For example:
Annotations based composition
public class TestcontainersConfiguration {
@JdbcServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(DockerImageName.parse("postgres:15.1"));
static {
postgres.start();
}
}
@SpringBootTest(classes = SpringBoot31DemoApplication.class)
@ContextConfiguration(classes = TestcontainersConfiguration.class)
class AppServiceConnectionCompositionTests {
@Test
void contextLoads(@Autowired JdbcTemplate jdbcTemplate) {
}
}
Interface based composition
@Testcontainers
public interface WithContainers {
@JdbcServiceConnection
@Container
PostgreSQLContainer postgres = new PostgreSQLContainer(DockerImageName.parse("postgres:15.1"));
}
@SpringBootTest
class AppServiceConnectionInterfaceCompositionTests implements WithContainers {
@Test
void contextLoads() {
}
}
I've made a prototype of ServiceConnectionContextCustomizerFactory supporting configuration classes declared in @ContextConfiguration. I am pretty sure it does not cover all the edge cases but I hope it makes it clear what I have in mind.
https://github.com/maciej-scratches/spring-boot-3.1-service-connection-demo/blob/main/src/test/java/org/springframework/boot/test/autoconfigure/service/connection/CustomServiceConnectionContextCustomizerFactory.java
Comment From: philwebb
With #35022 pushed I think it should be possible to use standard @TestConfiguration for this. Something like:
@TestConfiguration
public class TestcontainersConfiguration {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgres() {
return new PostgreSQLContainer<>(DockerImageName.parse("postgres:15.1"));
}
}
@SpringBootTest(classes = SpringBoot31DemoApplication.class)
@Import(TestcontainersConfiguration.class)
class AppServiceConnectionCompositionTests {
@Test
void contextLoads(@Autowired JdbcTemplate jdbcTemplate) {
}
}
I've not had a chance to actually test this yet.
Comment From: mhalbritter
Yep, this works, @philwebb, just tested it. Is this what you had in mind, @maciejwalkowiak ?
Comment From: maciejwalkowiak
Yes, exactly! Thanks!