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();
  }
}

References