Share postgres testcontainers among test classes
Create a PostgresTestContainerExtension
:
public class PostgresTestContainerExtension implements BeforeAllCallback {
static PostgreSQLContainer<?> postgres;
@Override
public void beforeAll(ExtensionContext context) throws Exception {
if (postgres == null) {
postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.waitingFor(new HostPortWaitStrategy())
.withInitScript("postgres/init.sql");
postgres.start();
System.setProperty("db.host", "localhost");
System.setProperty("db.port", Integer.toString(postgres.getFirstMappedPort()));
System.setProperty("db.username", postgres.getUsername());
System.setProperty("db.password", postgres.getPassword());
System.setProperty("db.database", postgres.getDatabaseName());
}
}
}
testcontainers will handle automatically stopping the container.
Then you can use in your tests:
@ExtendWith(PostgresTestContainerExtension.class)
class DatabaseIT {
@Test
void doSomeTest() {
// Your postgres container will be up and running.
}
}
If you are using spring-boot, and might need to add some spring related configuration, you you can also create a PostgresExtension
annotation like this:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(PostgresTestContainerExtension.class)
@TestPropertySource(
properties = {
"spring.config.import=classpath:/database.yml,classpath:/db-migration.yml",
"spring.jpa.hibernate.ddl-auto=validate",
"spring.datasource.password=${db.password:}",
// Prevent any in memory db from replacing the data source. See @AutoConfigureTestDatabase.
"spring.test.database.replace=NONE"
})
public @interface PostgresExtension {}
and instead of @ExtendWith(PostgresTestContainerExtension.class)
, use @PostgresExtension
:
@PostgresExtension
// For example, you want to test your JPA repository.
@DataJpaTest
void DatabaseIT {
@Autowired
private FoobarRepository foobarRepository;
@Test
void doSomeTest() {
// Your postgres container will be up and running.
var list = foobarRepository.findAll();
}
}