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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With