Easy Integration Testing With Testcontainers
Easy Integration Testing With Testcontainers
Always wanted to know how integration testing can be made easy? See for yourself how you can use testcontainers for easy integration testing with Spring Boot.
Join the DZone community and get the full member experience.Join For Free
In this post, we will take a look at how we can use Testcontainers for our integration tests. Testcontainers will allow us to write integration tests making use of containerized databases, message queues, web browsers, etc. without a dependency on a local installation.
A common problem when writing integration tests, is the dependency on installed components where the integration tests are supposed to run. Think about databases, message queues, web browsers, etc. Wouldn’t it be great when we could spin off a database instance in a Docker container when starting our integration test? We would always start with a clean database and our integration tests could run on any machine. This is where Testcontainers are designed for. Testcontainers is a Java library which can be used in JUnit tests.
In the next sections, we will create an integration test which is dependent on a PostgreSQL database. We will use the small CRUD Spring Boot application from our previous post. In short, the application is able to add an employee and to retrieve a list of all employees by means of a REST interface. The data is being stored in a PostgreSQL database.
The source code in this post is available at GitHub in branch
2. Create Integration Test
First thing to do is to create an integration test. We will do so for retrieving the list of employees. In a real application it is advised to separate your unit tests from your integration tests. We are not going to explore this in depth in this post, but we will use Spring profiles in order to be able to run our tests when a specific profile is used. If you want to separate unit tests from integration tests, you can simply create and use different profiles based on this example.
In our integration test, we call the
getAllEmployees URL, check the HTTP response status and check the content which is retrieved. Remember that we used Liquibase for creating and migrating the database and that we inserted one employee in the database when the Spring profile
test is being used.
Run the test:
Obviously this fails because we do not have a running database:
The solution for this problem is using Testcontainers.
3. Use Testcontainers
We need a PostgreSQL database in order to run the integration test we wrote. We can do so by using the Spring Boot Testcontainers. In order to use these, we need to insert the
embedded-postgresql and the
junit-jupiter testcontainers dependencies to our
We add a file
test/resources/bootstrap-test.properties where we enable the embedded PostgreSQL database and where we define the Docker image to be used and the database access credentials.
We also move the
application-test.properties we created in our previous post to the
test/resources directory. We change the
datasource properties in order to use the properties as we configured in the
Last thing to do is to add the Testcontainer to our integration test. Beware that the configuration for using Testcontainers which is being used, is only available from Spring Boot 2.2.6, see the corresponding blog.
We add the
@Testcontainers annotation, we create a PostgreSQL instance annotated with
@Container and we add the PostgreSQL properties annotated with the
@DynamicPropertyResource. The latter will allow the PostgreSQL related beans to communicate with the PostgreSQL instance running in the Testcontainers-managed Docker container.
Run the test again:
Our integration test now succeeds successfully.
4. Create addEmployee Integration Test
In order to complete the integration test, we also add an integration test for the
addEmployee REST interface. We want to validate whether the employee is really added to the database. We therefore extend the
EmployeeDAO with a
addEmployee integration test is the following:
We inject the
employeeDAO because we want to verify whether the employee is added to the database in Line 24. The test is annotated with
@Transactional, this will ensure that the database changes during the test are rollbacked after the test. If we do not add this annotation, the
getAllEmployees integration test would fail when it is executed after the
addEmployee test (because of an extra record in the database). We use
JdbcTestUtils and the injected
jdbcTemplate to verify the number of rows before and after the REST call.
We have been using Testcontainers in order to execute some integration tests. Using Testcontainers is fairly easy and it gives us the opportunity to create integration tests without the need of pre-installed components. We just add a Testcontainer which is started at the beginning of the integration test and use the component from within the running integration tests.
Published at DZone with permission of Gunter Rotsaert , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.