Spring Boot tests with Testcontainers and PostgreSQL, MySQL or MariaDB
Testcontainers is a Java library that allows integrating Docker containers in JUnit tests with ease. In a Containerized World, there is little sense to complicate the tests configuration with embedded databases and services. Instead, use run your services in Docker and let the Testcontainers manage this for you.
In this blog post you will learn how to configure Testcontainers to run PostgreSQL, MySQL and MariaDB in Spring Boot 2 integration tests.
This blog post covers:
- Testcontainers configuration (via JDBC URL Scheme) for Spring Boot 2 tests with PostgreSQL, MySQL and MariaDB
- Testcontainers in
@DataJpaTest
Dependencies
In order to use Testcontainers add the following dependencies to the pom.xml
(assuming Maven based project):
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | < properties > < org.testcontainers.version >1.12.5</ org.testcontainers.version > </ properties > < dependency > < groupId >org.testcontainers</ groupId > < artifactId >testcontainers</ artifactId > < version >${org.testcontainers.version}</ version > < scope >test</ scope > </ dependency > < dependency > < groupId >org.testcontainers</ groupId > < artifactId >DATABASE</ artifactId > < version >${org.testcontainers.version}</ version > < scope >test</ scope > </ dependency > |
where the DATABASE
is one of postgresql
, mysql
, mariadb
.
Note: Testcontainers provides JUnit 5 (Jupiter) plugin, but in the scenario presented in this pluging won’t be needed.
Test datasource configuration
Steps to configure Testcontainers for Spring Boot tests:
- Set the driver to
org.testcontainers.jdbc.ContainerDatabaseDriver
which is a Testcontainers JDBC proxy driver. This driver makes will be responsible for starting the required Docker container when the datasource is initialized. - Set the dialect explicitly to implementation of the dialect for your database otherwise you get the exception while starting the application. This step is required when you use JPA in your application (via Spring Data JPA)
- Set the JDBC URL to
jdbc:tc:<database-image>:<version>:///
so that Testcontainers knows which database image to use.
PostgreSQL configuration:
The complete configuration:
1 2 3 | spring.datasource.driver- class -name=org.testcontainers.jdbc.ContainerDatabaseDriver spring.datasource.url=jdbc:tc:postgresql: 9.6 : /// spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect |
MySQL configuration:
1 2 3 | spring.datasource.driver- class -name=org.testcontainers.jdbc.ContainerDatabaseDriver spring.datasource.url=jdbc:tc:mysql: 8 : /// spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect |
MariaDB configuration:
1 2 3 | spring.datasource.driver- class -name=org.testcontainers.jdbc.ContainerDatabaseDriver spring.datasource.url=jdbc:tc:mariadb: 10.3 : /// spring.jpa.database-platform=org.hibernate.dialect.MariaDB103Dialect |
See more on database configuration in the official documentation here: https://www.testcontainers.org/modules/databases/
Initializing test database with Testcontainers
You may initialize the database with the script loaded by Testcontainers. The file can be loaded either directly from the classpath or from any location. The only thing to do is to change the JDBC URL:
1 | spring.datasource.url=jdbc:tc:postgresql: 9.6 : ///?TC_INITSCRIPT=file:src/main/resources/init_db.sql |
or
1 | spring.datasource.url=jdbc:tc:postgresql: 9.6 : ///?TC_INITSCRIPT=classpath:init_db.sql |
@DataJpaTest
In order to use TC in @DataJpaTest
you need to make sure that the application defined (auto-configured) datasource is used. You can do it easily by annotating your test with @AutoConfigureTestDatabase
as shown below:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | @DataJpaTest @AutoConfigureTestDatabase (replace = AutoConfigureTestDatabase.Replace.NONE) public class OwnerRepositoryTests { @Autowired private OwnerRepository ownerRepository; @Test void findAllReturnsJohnDoe() { // as defined in tc-initscript.sql var owners = ownerRepository.findAll(); assertThat(owners.size()).isOne(); assertThat(owners.get( 0 ).getFirstName()).isEqualTo( "John" ); assertThat(owners.get( 0 ).getLastName()).isEqualTo( "Doe" ); } } |
@SpringBootTest
@SpringBootTest
will use application defined datasource, so no additional changes are needed.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc public class OwnerResourceTests { @Autowired WebApplicationContext wac; @Test void findAllReturnsJohnDoe() throws Exception { given() .webAppContextSetup(wac) .when() .get( "/owners" ) .then() .status(HttpStatus.OK) .body( "_embedded.owners.firstName" , containsInAnyOrder( "John" ), "_embedded.owners.lastName" , containsInAnyOrder( "Doe" ) ); } } |
Summary
You have just learned the easiest way to configure PostgreSQL, MySQL and MariaDB with Testcontainers in Spring Boot integration tests. This solution is well suited for rather simple setup. If you need more control over the Docker images, please consult official Testcontainers documentation.
Source code
The source code for this article can be found on Github: https://github.com/kolorobot/spring-boot-tc
See also
Published on Java Code Geeks with permission by Rafal Borowiec, partner at our JCG program. See the original article here: Spring Boot tests with Testcontainers and PostgreSQL, MySQL or MariaDB Opinions expressed by Java Code Geeks contributors are their own. |