DEV Community

Geoff Bourne
Geoff Bourne

Posted on

Spring Boot DataJdbcTest with PostgreSQL and Liquibase

In this article I wanted to share a little journey I took creating a Spring Boot unit test that exercises a Spring Data JDBC repository running against a Postgresql database initialized with Liquibase. I made a couple of mistakes along the way that I wanted to document here and provide the solutions for those.

In the Spring Initializr I chose the dependencies:

  • Spring Data JDBC
  • Liquibase Migration
  • PostgreSQL Driver

To initialize the schema, I created the Liquibase changelog file at src/main/resources/db/changelog/db.changelog-master.yaml where I create a user table:

databaseChangeLog: - changeSet: id: 1 author: gdb changes: - createTable: tableName: user columns: - column: name: id autoIncrement: true type: BIGINT constraints: primaryKey: true nullable: false - column: name: identifier type: VARCHAR(50) constraints: nullable: false - column: name: issuer type: VARCHAR(100) constraints: nullable: true 
Enter fullscreen mode Exit fullscreen mode

The User entity record/class is declared as

import org.springframework.data.annotation.Id; public record User( @Id Long id, String identifier, String issuer ) { } 
Enter fullscreen mode Exit fullscreen mode

And finally, the CRUD repository interface:

import org.springframework.data.repository.CrudRepository; public interface UserRepository extends CrudRepository<User, Long> { } 
Enter fullscreen mode Exit fullscreen mode

At first I started with the test class written as

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.jdbc.DataJdbcTest; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import static org.assertj.core.api.Assertions.assertThat; @Testcontainers @DataJdbcTest class UserRepositoryTest { @Container static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16"); @Autowired UserRepository userRepository; @Test void saveUser() { final User result = userRepository.save( new User(null, "name1", "issuer1") ); assertThat(result.id()).isNotNull(); } } 
Enter fullscreen mode Exit fullscreen mode

but that resulted in the error

Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Failed to instantiate [liquibase.integration.spring.SpringLiquibase]: Factory method 'liquibase' threw exception with message: Error creating bean with name 'dataSource': Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of @AutoConfigureTestDatabase. 
Enter fullscreen mode Exit fullscreen mode

It was one of those errors that actually tells you the solution. Nice! So, I added:

@Testcontainers @AutoConfigureTestDatabase( replace = AutoConfigureTestDatabase.Replace.NONE ) @DataJdbcTest class UserRepositoryTest { 
Enter fullscreen mode Exit fullscreen mode

The next error was

Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Failed to determine a suitable driver class 
Enter fullscreen mode Exit fullscreen mode

I remembered that Spring Boot added the service connections feature, so added that to the container field's declaration:

 @Container @ServiceConnection static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16"); 
Enter fullscreen mode Exit fullscreen mode

Now the test passes!

Top comments (0)