Open hendrikebbers opened 1 year ago
The use case makes a lot of sense, but I probably don't see this feature like this going into our JUnit Jupiter extension for now, because of a conceptual overlap with Reusable Containers.
It looks a little bit like dependency injections for containers to me. While I understand that it is a useful feature, I have a gut feeling that it might end up more complex as expected. I'd like to discuss if your use case can be implemented with our existing reuse capabilities and if not, and we think exploring this idea is worth a shot, doing it initially in a dedicated repo and as a dedicated extension might make more sense, to have more experimentation freedom to get it right.
I have a similar request. I made it work by using JUnit suites. I want to reuse containers across all tests within a @Suite
, without impacting single test runs, i.e. always stop all containers. I made this work, albeit ugly, by adding the following to the abstract superclass of each test:
public static final SomeContainer CONTAINER_1 = new SomeContainer().withReuse(true);
public static final SomeOtherContainer CONTAINER_2 = new SomeOtherContainer().withReuse(true);
public static final YetOtherContainer CONTAINER_3 = new YetOtherContainer().withReuse(true);
@BeforeAll
static void startContainers() {
CONTAINER_1.start();
CONTAINER_2.start();
CONTAINER_3.start();
}
@AfterAll
static void stopContainers() {
if (!TestcontainersConfiguration.getInstance().environmentSupportsReuse()) {
CONTAINER_1.stop();
CONTAINER_2.stop();
CONTAINER_3.stop();
}
}
And the following to the suite:
@BeforeSuite
static void beforeSuite() {
TestContainersUtil.setReuseEnabled(true);
}
@AfterSuite
static void afterSuite() {
CONTAINER_1.stop();
CONTAINER_2.stop();
CONTAINER_3.stop();
TestContainersUtil.setReuseEnabled(false);
}
Where the util is like this:
public class TestContainersUtil {
private static final File PATH =
new File(System.getProperty("user.home"), ".testcontainers.properties");
public static void setReuseEnabled(boolean reuseEnabled) {
try {
Properties properties = new Properties();
properties.load(new FileInputStream(PATH));
properties.setProperty("testcontainers.reuse.enable", String.valueOf(reuseEnabled));
properties.store(new FileOutputStream(PATH), null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
So, when running the suite, it starts the containers as soon as the first test starts and doesn't stop them after each test, only after the whole suite. When running a single test, it starts/stops the containers before/after that test.
I would prefer a more elegant way. Even just being able to simply control testcontainers.reuse.enable
using System.setProperty
would be nice.
Module
Core
Problem
Assume you have several integration tests splitted in some classes. All this tests can reuse the same container instance. If the container needs some time to setup that would be a great benefit.
Solution
By using the JUnit extension API it would be easy to create a custom annotation like this:
@ContainerConfig(name="containerA", needNewInstance=false) public void testFoo() {}
A container that is needed could be simply defined by a provider:
@ContainerProvider(name="containerA") public GenericContainer<?> createContainerA() {}
By using test lifecycle callbacks (https://junit.org/junit5/docs/current/user-guide/#extensions-lifecycle-callbacks) this could be achieved as a JUnit extension.
I would be happy to help by creating the feature :)
Benefit
Containers that are needed for multiple tests in multiple classes only need to be defined once and the instances can be reused.
Alternatives
-
Would you like to help contributing this feature?
Yes