Proposal for new ShutdownStrategy with a JVM ShutdownHook
Opened this issue · 0 comments
What happened?
We usually run lots of test together in our IDE with a SpringBootExtension starting up a SpringBoot container for all tests. The container keeps running unless I use @DirtiesContext. The Spring Contexts shuts down with a JVM Shutdown Hook after all tests have been running.
What did you want to happen?
I would like to use the same approach for my docker compose. I know, each test should run in isolation. But its a trade off between fast tests and isolation. So I want my docker-compose infrastructure to be up and running for all tests.
Further more I need to inject the database properties into the Spring context. So if my DockerComposeExtension is shutting down after each test class I need to referesh the Spring boot context all the time which involves running my database migrations with Flyway again and again.
I have managed to get this running with the following code. Maybe it is of interest for someone or a good idea to add this possibility to this project:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(Profil.INTEGRATION)
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@ComponentScan(basePackageClasses = IntegrationTest.class)
public abstract class IntegrationTest {
@Order(1)
@RegisterExtension
public static DockerComposeExtension docker = DockerComposeExtension.builder()
.file("docker-compose.yml")
.shutdownStrategy(new JvmShutdownStrategy())
.build();
@Order(2)
@RegisterExtension
public static PostgresqlExtension postgresqlExtension = new PostgresqlExtension(docker);
}
import com.palantir.docker.compose.configuration.ShutdownStrategy;
import com.palantir.docker.compose.execution.Docker;
import com.palantir.docker.compose.execution.DockerCompose;
import com.palantir.docker.compose.execution.KillDownShutdownStrategy;
public class JvmShutdownStrategy implements ShutdownStrategy {
private DockerCompose dockerCompose;
private Docker docker;
private KillDownShutdownStrategy killDownShutdownStrategy = new KillDownShutdownStrategy();
public JvmShutdownStrategy() {
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdownHook));
}
public void shutdownHook() {
try {
killDownShutdownStrategy.stop(dockerCompose);
killDownShutdownStrategy.shutdown(dockerCompose, docker);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void stop(DockerCompose dockerCompose) {
this.dockerCompose = dockerCompose;
}
@Override
public void shutdown(DockerCompose dockerCompose, Docker docker) {
this.dockerCompose = dockerCompose;
this.docker = docker;
}
}
public class PostgresqlExtension implements BeforeAllCallback, AfterAllCallback {
private static boolean started = false;
final static Lock lock = new ReentrantLock();
private final DockerComposeExtension docker;
public PostgresqlExtension(DockerComposeExtension docker) {
this.docker = docker;
}
@Override
public void beforeAll(ExtensionContext context) {
lock.lock();
if (!started) {
context.getRoot().getStore(GLOBAL).put(PostgresqlExtension.class.getName(), this);
var url = docker
.containers().container("postgresql")
.port(5432)
.inFormat("jdbc:postgresql://$HOST:$EXTERNAL_PORT/testdb");
System.setProperty("spring.datasource.url", url);
started = true;
}
lock.unlock();
}
@Override
public void afterAll(ExtensionContext context) {
}
}