3

I have several test nodes, but I run the container as a singleton.


@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(initializers = ApplicationTests
                .DockerPostgresDataSourceInitializer.class)
public abstract class ApplicationTests {

   

    static PostgreSQLContainer<?> postgresSQLContainer;

    static {
        postgresSQLContainer = new PostgreSQLContainer<>("postgres:14")
                .withUsername("test")
                .withPassword("test")
                .withInitScript("sql/init.sql")
                .withDatabaseName("test")
                .withReuse(true);


        postgresSQLContainer.start();
    }

    public static class DockerPostgresDataSourceInitializer
            implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        String jdbcUrl = "spring.datasource.url=" + postgresSQLContainer.getJdbcUrl();
        String username = "spring.datasource.username=" + postgresSQLContainer.getUsername();
        String password = "spring.datasource.password=" + postgresSQLContainer.getPassword();

        @Override
        public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {

            TestPropertySourceUtils
                    .addInlinedPropertiesToEnvironment(applicationContext, jdbcUrl, username, password);
        }
    }



    @Test
    void contextLoads() throws SQLException {

        ResultSet resultSet = performQuery(postgresSQLContainer);
        resultSet.next();

        int columnIndex = 1;

        int columnAmountExpected = 1;

        int result = resultSet.getInt(columnIndex);
        assertEquals(columnAmountExpected, result);

        Assertions.assertThat(postgresSQLContainer.isRunning()).isTrue();
    }




    private ResultSet performQuery(@SuppressWarnings("rawtypes") PostgreSQLContainer postgreSQLContainer)
            throws SQLException {

        String query = "SELECT 1";

        String jdbcUrl = postgreSQLContainer.getJdbcUrl();
        String username = postgreSQLContainer.getUsername();
        String password = postgreSQLContainer.getPassword();

        Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
        return conn.createStatement().executeQuery(query);
    }
}

The singleton container is started only once when the base class is loaded. The container can then be used by all inheriting test classes. At the end of the test suite the Ryuk container that is started by Testcontainers core will take care of stopping the singleton container.

enter image description here

The Ryuk container does not stop the database container. but he completes his work.

Maybe someone has ideas on how to fix it ?

skyho
  • 1,438
  • 2
  • 20
  • 47

2 Answers2

3

When using withReuse(true) and having reusable mode enabled, Ryuk won't remove containers. This works by design. Don't use reusable mode if you want containers to be cleaned by Ryuk.

Kevin Wittek
  • 1,369
  • 9
  • 26
  • but it worked in the old versions. I used only one container and reused it. The use of each container for each node test (and there are a lot of these nodes), then the assembly will take from 15 minutes or more. It is expensive. What should we do then ? – skyho Jun 20 '22 at 12:15
  • Sorry, I don't understand your question. The reusable mode is about reusing containers across test runs, i.e. across JVM processes. This feature is orthogonal from reusing containers across different tests during one test suite execution, i.e. within a single JVM process. Reusable mode always worked like this and is considered experimental. – Kevin Wittek Jun 20 '22 at 19:20
0

static {
     postgresSQLContainer = new PostgreSQLContainer<>("postgres:14")
             .withUsername("web")
             .withPassword("web")
             .withInitScript("sql/init.sql")
             .withDatabaseName("table_name")
             .withReuse(false);


     postgresSQLContainer.start();
 }

skyho
  • 1,438
  • 2
  • 20
  • 47
  • .withReuse(false); - really solved the problem, but then I don't understand its benefit in the value -> true – skyho Jun 20 '22 at 14:19
  • 1
    reusable `true` allows you to use the same container across several contexts or test runs. If I understand correctly, you have one base class that starts the context + container and then children that use it, in this case you don't need reusable, since only one container will start – dpozinen Dec 14 '22 at 19:35