Spring testcontainers Driver org.testcontainers.jdbc.ContainerDatabaseDriver claims to not accept jdbcUrl
Asked Answered
C

3

13

Having following configuration for my integration tests I ran into following exception:

Driver org.testcontainers.jdbc.ContainerDatabaseDriver claims to not accept jdbcUrl, jdbc:postgresql://localhost:32864/test?loggerLevel=OFF

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WebApplication.class)
@AutoConfigureMockMvc
@Testcontainers
@TestPropertySource(ResourceUtils.CLASSPATH_URL_PREFIX + "application-test.properties")
public abstract class AbstractIntegrationTest {

    @Autowired
    protected MockMvc mockMvc;

    @Container
    protected static PostgreSQLContainer<?> postgresqlContainer = new PostgreSQLContainer<>();

    @DynamicPropertySource
    static void postgresqlProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgresqlContainer::getJdbcUrl);
        registry.add("spring.datasource.username", postgresqlContainer::getUsername);
        registry.add("spring.datasource.password", postgresqlContainer::getPassword);
    }

    @Test
    void contextLoads() {
        Assertions.assertThat(mockMvc).isNotNull();
        Assertions.assertThat(postgresqlContainer.isRunning()).isTrue();
    }
}

The postgresqlContainer.getJdbcUrl() returns jdbc:postgresql://localhost:32864/test?loggerLevel=OFF But it should return jdbc:tc:postgresql://..., its missing the tc part.

Any solution to this ?

Hardcoding it like: String.format("jdbc:tc:postgresql://localhost:%s/%s", postgresqlContainer.getFirstMappedPort(), postgresqlContainer.getDatabaseName()) seems to work.

What am I doing wrong here?

Cinematograph answered 22/4, 2020 at 9:50 Comment(0)
P
18

Please see the big orange warning here: https://www.testcontainers.org/modules/databases/jdbc/

You should use either the JDBC URL with tc: prefix and ContainerDatabaseDriver or container instance with getJdbcUrl() and the original driver (or let the system detect the driver for you), not both.

Philosopher answered 24/4, 2020 at 9:45 Comment(2)
And given that the postgreSqlContainer is generating the jdbc, how do you pepuse to add the 'tc:' prefix?Subsidence
@EranFriedland I do it like this now: registry.add("spring.datasource.url", () -> "jdbc:tc:postgresql:13.11://ignored:1111/" + postgreSQLContainer.getDatabaseName()); whereas registry is a DynamicPropertyRegistry (method argument of a method annotated with @DynamicPropertySource)Boa
H
5

In my case just added the postgresql dependency (it includes the driver) and it worked:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.3.0</version>
</dependency>

My test class:

import org.junit.Rule;
import org.junit.Test;
import org.junit.platform.commons.annotation.Testable;
import org.testcontainers.containers.PostgreSQLContainer;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.LogManager;

import static org.junit.jupiter.api.Assertions.assertEquals;

@Testable
public class PostgreSqlContainerLiveTest {

    @Rule
    public PostgreSQLContainer postgresContainer = new PostgreSQLContainer("postgres:9.4");

    static {
        // Postgres JDBC driver uses JUL; disable it to avoid annoying, irrelevant, stderr logs during connection testing
        LogManager.getLogManager().getLogger("").setLevel(Level.OFF);
    }

    @Test
    public void whenSelectQueryExecuted_thenResultsReturned() throws Exception {
        ResultSet resultSet = performQuery(postgresContainer, "SELECT 1");
        resultSet.next();
        int result = resultSet.getInt(1);
        assertEquals(1, result);
    }

    private ResultSet performQuery(PostgreSQLContainer postgreSQLContainer, String query) throws SQLException {
        String jdbcUrl = postgreSQLContainer.getJdbcUrl();
        String username = postgreSQLContainer.getUsername();
        String password = postgreSQLContainer.getPassword();

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

I hope that this could help to you or someone else.

Hype answered 20/1, 2022 at 19:26 Comment(0)
G
1

Make sure you have both dependency testcontainers postgresql & dependency postgresql at your config file.

Guncotton answered 4/2, 2023 at 1:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.