Write Spring Boot Integration Tests With Testcontainers (JUnit 4 & 5)

Last Updated:  August 27, 2021 | Published: June 9, 2018

Recently, I was looking for a solution to write integration tests for my Spring Boot-based application which was using PostgreSQL. I had the following requirements for this task:

  1. The integration tests should use the same database as in production (referring to the Twelve-Factor App I wanted to keep my environment during the tests as similar as possible to the production environment)
  2. The tests should not need any pre-setup before running (e.g. like manually setting up a test database)
  3. The tests should use my Flyway DDL scripts and create-drop (spring.jpa.hibernate.ddl-auto) shouldn't be activated  for my tests
  4. Seamless integration when testing Spring Boot applications

For this task, I found the awesome project: Testcontainers. The project describes itself as the following:

“Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.”

With this blog post, we'll use Testcontainers to write integration tests with JUnit using a real database (meaning not mocked or in-memory) for a Spring Boot application.

UPDATE: Time flies and a lot was introduced since I published this blog post. Therefore I added integration test examples for different combinations of JUnit 4 & 5 and Spring Boot versions.

Setup Testcontainers in Spring Boot project

For using this dependency you need to have Docker on your local machine/on your build server (Jenkins etc.). With Testcontainers you can use a @ClassRule or @Rule on each of your integration tests and define the Docker image for your test (valid for JUnit 4.12). For MySQL and PostgreSQL and there are already built-in solutions but you are free to use an image of your choice like the following:

To run the integrations tests after your unit tests, simply add maven-failsafe-plugin to your project. In addition, make sure your integration tests have IT as a postfix:

Integration Tests with Testcontainers and JUnit 4

Using: JUnit 4.12 and Spring Boot < 2.2.6

Let's start with the integration test each Spring Boot application contains out-of-the-box. This integration test verifies that Spring can create the context and start the application.

As our application requires a PostgreSQL to be available during startup, we can provide one using Testcontainers. Overriding the properties to use the PostgreSQL database spawned by Testcontainers is as easy as the following:

Furthermore, you can find a video tutorial for this setup here.

Integration Tests with JUnit 5 and Spring Boot > 2.2.6

If your application uses JUnit 5, you can't use the @ClassRule anymore. Fortunately, Testcontainers provides a solution to write tests with JUnit Jupiter:

With this dependency and a more recent version of Spring Boot (> 2.2.6) the basic integration test looks like the following:

In addition, you can find a video tutorial for this setup on YouTube.

Integration Tests with JUnit 5 and Spring Boot < 2.2.6

If your application makes use of JUnit 5 but is using a Spring Boot version < 2.2.6, you don't have access to the @DynamicPropertySource feature.

A possible integration test to verify a REST API endpoint is working as expected looks like the following:

You can find more integration test examples for this demo Spring Boot CRUD API application using PostgreSQL on GitHub.

Further integration test-related tutorials for Spring Boot:

Happy integration-testing with Spring Boot, Testcontainers, and JUnit,

Philip

  • […] Ensuring your application is working properly is a critical part of continuous integration and delivery. Unit tests help you to test your methods’ business logic for both normal & edge cases. When it comes to guaranteeing that your users are able to correctly work with your application, we need something different. If your application exposes a frontend with user interaction, we can write functional tests to ensure different use cases are working. With this blog post, I’ll provide an example of how to write Functional Tests for Spring Boot applications using Selenium and Testcontainers. […]

  • Do you have any idea why the integration test IndexControllerIT does not run when I execute mvn verify? Only the ApplicationTest is executed. I suppose Maven’s integration test phase is not executed. I use Maven 3.6.3, if that is important.

    • Hi Jesper,

      did you include the Maven Failsafe Plugin in your project? The Surefire Plugin usually runs unit tests and the Failsafe plugin the integration test. It’s not part of Maven’s default plugins and hence needs to be manually added. You can find detailed information here.

      Let me know if that helps,
      Philip

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Join Our Mailing List To Get 3x Free Cheat Sheets

    Free Java Cheat Sheets
    >