Home > Software design >  How to have a database connection without failing unit tests with Spring Boot?
How to have a database connection without failing unit tests with Spring Boot?

Time:10-12

I have a simple Spring boot project that can connect to a PostgreSQL Database.

When I install the dependencies with mvn clean install, I get:

org.postgresql.util.PSQLException: The connection attempt failed during Maven install

A "solution" I found was using -DskipTests, but that doesn't solve the issue, it only postpones it.
Because when I do mvn test, I will get the same error.

How can we have a database connection that will not crash tests?


The dependencies are this:

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
...
    </dependencies>

PS:

The test is the automatically generated one, I think loading the context is what gives the error.

package com.hamza.ince.bonptitcoinapi;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class BonPtitCoinApiApplicationTests {

    @Test
    void contextLoads() {
    }
}
  • application.properties:
spring.datasource.url=jdbc:postgresql://postgresql-api:5432/annonce_db?user=annonce_username&password=annonce_password
spring.datasource.username= postgres
spring.datasource.password= password

spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true

spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect
spring.datasource.driver-class-name=org.postgresql.Driver

CodePudding user response:

There are multiple solutions possible:

  • Configure a dedicated test environment and use that url in your test profile configuration

  • Use an in-memory database

  • Use a framework like testcontainers to spin up your postgres test-database and pass the url to your application

Here's an example for the last one, use it in the appropriate beforeAll callback of the testing framework.

environment = new DockerComposeContainer<>(new File("path/to/docker-compose.yml"))
  .withLocalCompose(true)
  .withExposedService("postgres_1", 5432);

environment.start();

//build url with
//environment.getServiceHost("postgres_1", 5432)
//environment.getServicePort("postgres_1", 5432)
//pass as datasource via System.setProperty("spring.datasource.url" url)

or without docker-compose

    public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:11.1")
      .withDatabaseName("integration-tests-db")
      .withUsername("sa")
      .withPassword("sa");

// use getters to get host, username, password etc

This of course means whatever is executing your test in your test pipeline must be able to run docker containers.
Otherwise you'd have to go with in-memory db instead of postgres.

  • Related