How to reuse Testcontainers between multiple SpringBootTests?

10,628

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.

Share:
10,628

Related videos on Youtube

Martin Schröder
Author by

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, 2022

Comments

  • Martin Schröder
    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
    Martin Schröder almost 4 years
    "The Singleton pattern doesn't help since every test starts a new application."
  • Martin Schröder
    Martin Schröder almost 4 years
    Many 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
    rieckpil almost 4 years
    I 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
    Abbadon over 3 years
    Where is testcontainers.reuse.enable=true documented?
  • vault
    vault about 3 years
    Is 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
    rieckpil about 3 years
    Yes, there are multiple ways to configure this property. Take a look at the Configuration locations section of the Testcontainers documentation.
  • Yaroslav Buhaiev
    Yaroslav Buhaiev over 2 years
    You can't set testcontainers.reuse.enable via classpath. See this comment.
  • Gaurav Parek
    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
    rieckpil about 2 years
    Take 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
    Frankie Drake almost 2 years
    @vault You can do this via TestcontainersConfiguration.getInstance().updateUserConfig("‌​testcontainers.reuse‌​.enable", "true"); before starting the container
  • gstackoverflow
    gstackoverflow almost 2 years
    There are 2 calls of new PostgreSQLContainer() But only one container will be used. Is it correct ?
  • rieckpil
    rieckpil almost 2 years
    Yes, only one container will be created for the tests