Introduction about Testcontainers

Testcontainers is a library that helps us write unit tests for applications and databases running on a Docker container. Testcontainers will help us run applications or databases using Docker Images, then we will use the plugins it supports to implement the unit test code we want. Testcontainers supports many different languages, in addition to Java, it also has versions for Go, .Net, Node.js, Python, Rust, Haskell. In this tutorial, I will show you how to use Testcontainers for Java to write unit tests for the MySQL database manipulation part of a simple Java application.

First, I will create a new Maven project as an example:

I will declare Testcontainers and MySQL JDBC driver dependency for this project as follows:

As an example, I will define a student table in MySQL database with the following simple structure:

The data in the student table is as follows:

To get information in this student table, I will write JDBC code as follows:

with the Student class with the following content:

The main class to run this application is as follows:

Result:

To write unit tests for the getAllStudents() method to get student information from the database, in the past, you could use the H2 in-memory database. With this approach, our unit test code doesn’t actually run against the database we are using for the application. And so we can run into issues when running the application that the unit test code fails to detect.

Now you can use Testcontainers to solve this shortcoming. Testcontainer will help us to run unit test code against the real database that our application is using.

The disadvantage of this solution is that you must have Docker installed on the machine running the unit test, but this inconvenience is not a big problem, right?

To write unit tests for the StudentService class using Testcontainers, I will create a new class and annotate this class with the @Testcontainers annotation of the Testcontainer as follows:

This @Testcontainers annotation has a disabledWithoutDocker attribute that helps our unit test code with Testcontainers will automatically disable if the machine running the unit test does not have that Docker installed! The default value of this property is false which means that our unit test code will not be disabled if the machine running the unit test does not have Docker installed. Depending on the situation, you can add this attribute if you want. My machine is installing Docker, so I don’t need to declare this attribute.

Now we will declare the container that we will need to run before the unit test code is executed with the @Container annotation. My example will be like this:

By default, the MySQL container with Testcontainer will run with the user “root” and the password “test”. For my example, I changed the password to “123456” as you can see. My database name is “example”.

I also declare an initial SQL script so that when running the container, Testcontainers will automatically create a new students table and insert data into this table. The contents of the db.sql file located in the src/test/resources directory are as follows:

The withReuse() method makes it possible to reuse the container we created earlier.

To run the container that we have declared above, you can call the start() method in the annotated method with the @BeforeAll annotation of JUnit 5 as follows:

As you can see, I also initialized the Connection object from the information of the MySQL container that I ran.

Now, you can write unit tests for the getAllStudents() method as follows:

My entire unit test code for the StudentService class is as follows:

Result:

Add Comment