How to reuse Testcontainers between multiple SpringBootTests?
Solution 1
You can't use the JUnit Jupiter annotation @Container
if you want to have reusable containers. This annotation ensures to stop the container after each test.
What you need is the singleton container approach, and use e.g. @BeforeAll
to start your containers. Even though you then have .start()
in multiple tests, Testcontainers won't start a new container if you opted-in for reusability using both .withReuse(true)
on your container definition AND the following .testcontainers.properties
file in your home directory:
testcontainers.reuse.enable=true
A simple example might look like the following:
@SpringBootTest
public class SomeIT {
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll() {
postgreSQLContainer.start();
}
@Test
public void test() {
}
}
and another integration test:
@SpringBootTest
public class SecondIT {
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll() {
postgreSQLContainer.start();
}
@Test
public void secondTest() {
}
}
There is currently a PR that adds documentation about this
I've put together a blog post explaining how to reuse containers with Testcontainers in detail.
Solution 2
If you decide go forward with the singleton pattern, mind the warning in "Database containers launched via JDBC URL scheme". I took hours till I note that, even though I was using the singleton pattern, an additional container was always being created mapped on a different port.
In summary, do not use the test containers JDBC (host-less) URIs, such as jdbc:tc:postgresql:<image-tag>:///<databasename>
, if you need use the singleton pattern.
Related videos on Youtube
Martin Schröder
TeX user since 1989, mostly LaTeX. For some time maintainer of pdfTeX, then a close friend of the LuaTeX team. http://meta.tex.stackexchange.com/questions/430/text-building-blocks
Updated on June 04, 2022Comments
-
Martin Schröder almost 2 years
I'm using TestContainers with Spring Boot to run unit tests for repositories like this:
@Testcontainers @ExtendWith(SpringExtension.class) @ActiveProfiles("itest") @SpringBootTest(classes = RouteTestingCheapRouteDetector.class) @ContextConfiguration(initializers = AlwaysFailingRouteRepositoryShould.Initializer.class) @TestExecutionListeners(listeners = DependencyInjectionTestExecutionListener.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @Tag("docker") @Tag("database") class AlwaysFailingRouteRepositoryShould { @SuppressWarnings("rawtypes") @Container private static final PostgreSQLContainer database = new PostgreSQLContainer("postgres:9.6") .withDatabaseName("database") .withUsername("postgres") .withPassword("postgres");
But now I have 14 of these tests and every time a test is run a new instance of Postgres is spun up. Is it possible to reuse the same instance across all tests? The Singleton pattern doesn't help since every test starts a new application.
I've also tried
testcontainers.reuse.enable=true
in.testcontainers.properties
and.withReuse(true)
, but that didn't help. -
Martin Schröder almost 4 years"The Singleton pattern doesn't help since every test starts a new application."
-
Martin Schröder almost 4 yearsMany thanks. Then I also need to increase my
max_connections
with.withCommand("postgres -c max_connections=200")
. How can I control the lifetime of reusable containers? -
rieckpil almost 4 yearsI can't answer this question. Maybe it's worth having a look at the PR which introduced the feature: github.com/testcontainers/testcontainers-java/pull/1781
-
Abbadon over 3 yearsWhere is testcontainers.reuse.enable=true documented?
-
vault about 3 yearsIs there a way to configure
testcontainers.reuse.enable=true
elsewhere? I don't want reusable containers to be dependant on the developer's laptop configuration -
rieckpil about 3 yearsYes, there are multiple ways to configure this property. Take a look at the Configuration locations section of the Testcontainers documentation.
-
Yaroslav Buhaiev over 2 yearsYou can't set
testcontainers.reuse.enable
via classpath. See this comment. -
Gaurav Parek about 2 years@rieckpil how can we ensure that it is reusing the same container as I applied these settings and I do not see any time difference in my integration test run time. it seems to same with these conditions enabled and disabled. thanks
-
rieckpil about 2 yearsTake a look at docker ps while your tests are running. You should only see a single container being used. If you are on Linux/macOS
watch -n 1 docker ps
may be handy -
Frankie Drake almost 2 years@vault You can do this via
TestcontainersConfiguration.getInstance().updateUserConfig("testcontainers.reuse.enable", "true");
before starting the container -
gstackoverflow almost 2 yearsThere are 2 calls of new PostgreSQLContainer() But only one container will be used. Is it correct ?
-
rieckpil almost 2 yearsYes, only one container will be created for the tests