Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for new ShutdownStrategy with a JVM ShutdownHook #719

Open
kicktipp opened this issue Sep 6, 2022 · 0 comments
Open

Proposal for new ShutdownStrategy with a JVM ShutdownHook #719

kicktipp opened this issue Sep 6, 2022 · 0 comments

Comments

@kicktipp
Copy link

kicktipp commented Sep 6, 2022

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) {
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant