Search code examples
integration-testingquarkustestcontainers

How can I reuse containers during integration tests with quarkus?


I currently have a few integration tests that are running fine, however I'm using the annotation @QuarkusTestResource to launch containers via testcontainers before quarkus is launched and I adapt my properties to the random test container port by overriding the start method of my container class extending QuarkusTestResourceLifecycleManager.

To optimize a little bit I'd like for example to reuse my container that launches kafka since it takes 6-8 seconds to start it and reuse it for several of my integration tests. I've not been able to do so. Since Quarkus manages the lifecycle every times it stops, between every test class, it also stops every container. I tried mixing singleton containers from testcontainers with the Quarkus test resources but it doesn't work. Here's a snippet of the start of one of my integration test class :

@QuarkusTest
@Tag(INTEGRATION_TEST)
@QuarkusTestResource(value = KafkaNode.class, restrictToAnnotatedClass = true, parallel = true)
class MyIntegrationTest { ... }

And my KafkaNode class :

public class KafkaNode implements QuarkusTestResourceLifecycleManager {
    static KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.1"))
            .withNetworkAliases("kafkaNode")
            .withNetwork(CommonNetwork.getInstance());

    @Override
    public Map<String, String> start() {
        kafka.start();
        return Collections.singletonMap("myapp.kafka.servers",
                kafka.getBootstrapServers());
    }

    @Override
    public void stop() {
        kafka.close();
    }
}

I'm open to ideas to reuse of even rework my tests so that I can reuse containers in another way.


Solution

  • You can use the experimental reusable mode for your container via .withReuse(true).

    Please note that in order for this to work you need to:

    • set the testcontainers.reuse.enable=true property in the ~/.testcontainers.properties file
    • NOT call .close() (which programmatically stops the container in any way)

    Once you've setup everything accordingly your container should

    • not be stopped/garbage collected at the end of the test run anymore
    • be picked up again at the next test run - avoiding a new container start

    Please note that all runtime modifications (configuration, data, topics etc.) will still be there at the next test run. You need to take suitable measures to avoid non-deterministic tests - like using different / random topic names for each test run.

    Also note that you'll need to manually stop/delete the container when you're done with it. Testcontainers will not remove the container for you anymore.

    You can also read this article that describes how to do it from spring for inspiration: Reuse Containers With Testcontainers for Fast Integration Test