Testcontainers-java: Singleton Postgres container does not work.

Created on 4 Oct 2019  路  6Comments  路  Source: testcontainers/testcontainers-java

I've read the documentation about singleton containers, I've done as suggested, yet for postgres at least it does not work. For every test, I get a new container. What I did:

@RunWith(SpringRunner.class)
@SpringBootTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AsigApplicationTests extends AbstractAsigApplicationTest {

    @Autowired
    UserService userService;


    @Test
    public void contextLoads() {
        assertNotNull(postgreSQLContainer);
    }

    @Test
    public void userTest() {
        Integer tcDockerPort = postgreSQLContainer.getFirstMappedPort();
        assertNotNull(tcDockerPort);
        assertNotNull(userService);
        assertNotNull(userService.getInsuranceUserIndividual(StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, new BigDecimal(106), null, null, null, null, Long.valueOf(1), Long.valueOf(1000), Collections.emptyList(), Collections.emptyList()));
    }

}
public abstract class AbstractAsigApplicationTest {

    public static final PostgreSQLContainer<?> postgreSQLContainer;

    static {
        postgreSQLContainer = CustomPostgresContainer.getCustomPostgresContainerInstance();
        postgreSQLContainer.start();
    }

}
public class CustomPostgresContainer extends PostgreSQLContainer<CustomPostgresContainer>{
    private static final String IMAGE_VERSION = "postgres:9.6";
    private static CustomPostgresContainer customPostgresContainer;
    private static final String DB_NAME = "ASIGDB_TEST";
    private static final String DB_USER= "postgres";
    private static final String DB_PASSWORD= "postgres";


    public CustomPostgresContainer() {
        super(IMAGE_VERSION);
    }

    public static CustomPostgresContainer getCustomPostgresContainerInstance() {
        if(customPostgresContainer == null) {
            return extracted().withDatabaseName(DB_NAME)
                              .withUsername(DB_USER)
                              .withPassword(DB_PASSWORD);
        }

        return customPostgresContainer;
    }

    private static CustomPostgresContainer extracted() {
        return new CustomPostgresContainer();
    }
}

Most helpful comment

@Kiroshi

you're using jdbc:tc:-style container. It will start a container automatically on first connection and close when last connection is closed, so:

  1. You don't need to define a singleton if you use jdbc:tc: URLs
  2. See the daemon option to achieve what you want: https://www.testcontainers.org/modules/databases/#running-container-in-daemon-mode

All 6 comments

System info:
OS: WIN10
JDK: 1.8.0_102
TC: 1.12.2

Hi @Kiroshi
I can鈥檛 see how the JDBC URL from your singleton DB container is being passed through.

Where is the JDBC URL set?

Sent with GitHawk

Hi @Kiroshi
I can鈥檛 see how the JDBC URL from your singleton DB container is being passed through.

Where is the JDBC URL set?

Sent with GitHawk

Hi @rnorth
It's in a properties file under test/resources/META-INF/spring/database.properties:

#db props
database.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver
database.url=jdbc:tc:postgresql:9.6.12://localhost/ASIGDB_TEST
database.user=postgres
database.password=postgres
#db config
hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
hibernate.format_sql=true
hibernate.show_sql=false
hibernate.hbm2ddl.auto=false
entitymanager.packages.to.scan=com.adl.persistence.model

@Kiroshi

you're using jdbc:tc:-style container. It will start a container automatically on first connection and close when last connection is closed, so:

  1. You don't need to define a singleton if you use jdbc:tc: URLs
  2. See the daemon option to achieve what you want: https://www.testcontainers.org/modules/databases/#running-container-in-daemon-mode

Yeah, just to clarify, for database containers there are two very separate ways of using them, and they don't mix:

One way: have Container objects created in your test classes, and then inject the JDBC URL into your code under test. These container objects can be static singletons, @Rule-annotated fields, etc.

Second way: use a jdbc:tc: URL. If you do this, then Testcontainers' JDBC driver automatically creates the Container and manages its lifecycle.

Each of these ways is useful in different circumstances, but you can't mix them.

As @bsideup says, the daemon mode is probably the right thing for your tests here. You should be able to use that and just delete all the code relating to creating the static singleton container.

Indeed, using daemon option did work for me.
Thanks for the clarifications!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dabraham02124 picture dabraham02124  路  3Comments

itudoben picture itudoben  路  3Comments

aniketbhatnagar picture aniketbhatnagar  路  3Comments

richard77 picture richard77  路  3Comments

rnorth picture rnorth  路  3Comments