22. July 2019
4 min

Testcontainers - Bring Your Integration Tests to a New Level

In this blogpost, I am going to give you an overview of Testcontainers and do a comparison with demo project of Integration test implemented with Redis Testcontainers vs Emebedded Redis.

Microservices Testing, in specific integration testing has always been a topic of interest. Therefore, I would like to present you a framework for integration testing: Testcontainers.

My experience shows me that Testcontainers have a great potential to support integration testing, make our live easier and most of all have support for custom cases. With testcontainer you can:

  • use already existing official Docker containers
  • use custom Docker container
  • create Docker image from your own Dockerfile

Getting started: I have prepared a demo project with a Spring boot application written in Kotlin.

The Github project can be found here: https://github.com/nt-ca-aqe/blogposts/tree/master/testcontainers

Please follow the instructions in the README file for setting up the project. For being able to execute the test, you need to have a running Docker instance since Testcontainers use it.

In the application we have a REST Controller (VehicleController) that can get Vehicle by id and save a new vehicle into the Redis database. For the Redis implementation Spring Data Redis is being used with Lettuce as connection client. In this particular example we have implemented a custom redis repository for saving the data into Redis. In VehicleCustomRepositoryImpl can be found the repository implementation.

Once the implementation is done, you will want to test it. What options do you have? Option #1 is to test it manually by setting up a running Redis instance or Redis Docker Container on your machine, run the application, send some GET/POST requests and verify what is happening in Redis. This option is however no long term solution, every time you make a change you have to go through the same procedure. I like automating repeated actions and taking your time to sit down and write an integration test for your implementation is Option #2 or the option worth investing your time into. When it comes to writing integration tests we tend to ask ourselves – “What are the tooling options out there for our integration component?”. In this case it is Redis, in others it could be any specific framework that your project/organization has decided to use. The most used ones often come with some embedded support. If you go through the documentation of most of the embedded solutions you will see that it is mentioned that they are not one to one fully functional compared to non-embedded version. For simple operations this can be enough, but for more advanced once you will want to test it against a non-embedded implementation. In parallel to this, we live in the era of Containers. Containers are used more and more in daily activities and there is already an existing framework – Testcontainers that enables you to run docker container inside your test! I personally find this amazing. Moreover, most of the tools have official docker images, it is very unlikely to not find one.

Let’s have a look at the examples.

Example #1 uses embedded Redis. You can configure the port you want the server to be started. Before all tests the redis server will be started, tests are executed and afterwards server is stop.

Example #2 uses Testcontainers. You can use fixed port or dynamically assigned port. The example uses the JUnit5 support, there is JUnit4 alternative with @Rule (you also need to use another test container dependency). With the code line:

we say to Testcontainers to download the lastest image of redis from the official docker hub. The first port value is for the host system e.g. the port that our RedisConfiguration will need to connect to and the second one is the exposed port from the container. Standard value for Redis is 6379. When the test is being executed for the first time it can take longer since it needs to download the needed containers. You can see that in terms of implementation both tests – ContainerTest and EmbeddedTest do not differ so much. The main difference is what your tests are run against – an embedded version or a docker container. In case your organization is using private docker registry, you need to adjust the testcontainers configuration (.testcontainers.properties under user’s home folder) by providing your organization’s URLs for the containers that are being used. Otherwise by default Testcontainers will try to download the containers from the official repositories or docker hub. More information can be found in the official documentation: https://www.testcontainers.org/features/configuration/ .

My experience from the development teams is that at first Testcontainers sounds quite complex or could be considered too much overhead to set it up. But that is not true. You only need to take your time to try at least one test and see how smoothly it works. There is one little disadvantage in my view – it supports only the Java world technologies. As a testing concept, I find it quite unique because that solves the problem of relying on libraries that may or may not have embedded version or some type of support for integration testing. You can use the official Docker image and run your tests against it. My wish would be to have support or similar project for the other technologies, where you do not need to start your docker container in advance, but it is all handled by the test itself. That makes it completely independable and automated. There is one dependency of course on Docker, but who is not using Docker nowadays.

My suggestion is to give it a try!

Happy testing!

Cookies help us to improve your experience when surfing our website. By continuing to use this website, you agree to our use of cookies. Learn more