Build true-to-production tests with Testcontainers, JUnit and Open Liberty
Why do we need true-to-production tests?
In a world where our cloud-native Java applications are often deployed to the cloud in containers, it makes sense that we should also be testing these applications in containers. As the 12 factor and 15 factor methodologies promote, ensuring parity between our deployment environments builds confidence in our application’s expected behaviour and helps us spot and solve bugs.
Containers are an important part of this parity. One of the great benefits of containers (and container technologies like Docker) is that we get a nice consistent package that contains everything we need, down to the OS, that is portable to any hardware. So why not use these technologies to ensure we get consistent testing environments too?!
How, then, can we effectively utilise containers in our tests and ensure we’re testing our applications in a manner that is as true to production as possible? This is where the Testcontainers framework can help.
What is the Testcontainers framework?
Testcontainers is an open source library that provides containers as a resource at test time, creating consistent and portable testing environments. Breaking it down, it essentially wraps Docker in a Java API and offers first-class integration with JUnit.
Why is Testcontainers helpful?
Although this framework is especially useful for applications that have external resource dependencies (such as databases, message queues, or web services), one of the most important features of Testcontainers is generic support for any Docker image. By encapsulating any necessary dependencies in containers, Testcontainers simplifies the configuration process and ensures a uniform testing setup that closely mirrors production environments.
In essence, with Testcontainers, you can run your tests in an isolated and controlled environment that closely resembles your production setup, ensuring that your tests are reliable and reproducible.
As well as this increased reliability and reproducibility of tests, there are additional key features/benefits that make Testcontainers a really useful tool, including:
-
A wide range of supported containers
Testcontainers supports a large variety of Docker containers, including databases (e.g., PostgreSQL, MySQL, MongoDB, DB2, Redis), messaging brokers (e.g., RabbitMQ, Kafka), web servers, and more. This diversity enables you to customise test environments to make them specific to your application stack.
-
Integration with popular testing frameworks
Testcontainers integrates with popular testing frameworks including JUnit, TestNG, and Spock. You can easily and efficiently incorporate Testcontainers into your testing suite without having to make significant changes to your existing tests.
-
Declarative configuration
Testcontainers provides a simple, declarative API for configuring and deploying containers. You can define any desired properties of a container using code, making it easy to configure and maintain.
-
Lifecycle management
Testcontainers also handles the lifecycle of containers, ensuring they are started before the tests run and, importantly, stopped afterward. This automation removes this responsibility from your shoulders, eliminating the need for manual intervention and making it easy to maintain clean, isolated testing environments.
-
Wait strategies
To prevent your tests from trying to run before any required containers are set up, Testcontainers has a helpful, built-in wait strategy. This particularly important for services with tests that rely on services that can take significant time to initialise (e.g. databases).
How to use Testcontainers in your own applications
In our newest guide, we walk you through how you can add Testcontainers to an existing Java application. This interactive guide shows how to to set up and configure multiple containers, including the Open Liberty Docker container, to simulate a production-like environment for your tests. The guide uses Docker to run an instance of the PostgreSQL database needed in this application for a fast installation and setup.
As Testcontainers is a black-box form of testing, you need a REST client to trigger the requests for your tests. In this guide, we also show how to build a test REST client to accurately verify the application’s behavior by ensuring that it responds correctly to various scenarios and conditions.
Try it out for yourself, either running locally on your own machine or using our cloud-hosted development environment with our Testcontainers guide.