Introduction
In modern software development, it is crucial to write robust and reliable tests to ensure the quality of your applications. One essential aspect of testing is dealing with dependencies, such as databases or external services. Testcontainers is an excellent Java library that provides lightweight, disposable containers for running dependencies during tests. In this tutorial, we will explore how to use Testcontainers to set up a GenericContainer and a PostgreSQL container for your Java tests.
What is TestContainers ?
Testcontainers is an open source framework for running lightweight instances of Container Images as part of your Tests.
By utilizing Testcontainers, the need to set up complex environments to test services becomes obsolete. You can define your test dependencies as code, effortlessly execute your tests, and watch as containers are dynamically created and disposed of. With Testcontainers’ broad language and testing framework support, all that’s required is Docker to streamline your testing process.
Setting up Testcontainers
To get started with Testcontainers, you need to include the testcontainers library as a dependency in your Java project. For Maven, add the following to your pom.xml
file:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.18.3</version> <scope>test</scope> </dependency>
Additionally, include JUnit Test library to annotate your Tests. Check the following article to learn more about JUnit configuration: JUnit 5 Made Easy
Example: GenericContainer
The GenericContainer
class allows you to start a Docker container with a specified image. Let’s start with a simple example of running an httpd web server using Testcontainers.
@Testcontainers public class GenericContainerTest { private static final int HTTP_PORT = 80; @Container private static final GenericContainer<?> container = new GenericContainer<>("httpd:latest") .withExposedPorts(HTTP_PORT); @Test public void testHttpdServer() throws Exception { // Get the host and port of the running container String host = container.getHost(); int port = container.getMappedPort(HTTP_PORT); // Create the URL for the HTTP request URL url = new URL("http://" + host + ":" + port + "/"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // Send an HTTP GET request connection.setRequestMethod("GET"); connection.connect(); // Verify the response code is 200 (OK) int responseCode = connection.getResponseCode(); System.out.println("Response code:"+responseCode); Assertions.assertEquals(200, responseCode); } }
In this code snippet:
- The
@Testcontainers
annotation enables Testcontainers support for the test class. - The
@Container
annotation defines a static fieldcontainer
that represents the GenericContainer instance. - The
GenericContainer
is created with the image name “httpd:latest” and exposes the HTTP_PORT. - Then, we open an HTTP connection and send an HTTP GET request to the container.
- Finally, we verify the response code using
Assertions.assertEquals()
to ensure it is 200 (OK).
This code demonstrates the usage of Testcontainers to start a GenericContainer running an Apache HTTP server, perform an HTTP request, and verify the response code.

Another TestExample: A PostgreSQL Container
Besides the GenericContainer
there are several pre-built API to Test Services such as Databases, Brokers or Identity Servers. As an example, we will show here how to kickstart and Test a PostgreSQL container with PostgreSQLContainer.
Firstly, we need to add to our project the dependency for PostgreSQL TestContainer and a suitable Driver for PostgreSQL:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>postgresql</artifactId> <version>1.18.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.3.1</version> <scope>test</scope> </dependency>
Finally, here is our JUnit 5 Test which starts a PostgreSQL Database and executes a SELECT on the current Data when the Container is running:
@Testcontainers public class PostgreSQLTest { @Container private static final PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:latest"); private Connection connection; @BeforeAll public static void setUp() { postgresContainer.start(); } @BeforeEach public void connectToDatabase() throws Exception { String jdbcUrl = postgresContainer.getJdbcUrl(); String username = postgresContainer.getUsername(); String password = postgresContainer.getPassword(); connection = DriverManager.getConnection(jdbcUrl, username, password); } @AfterEach public void closeConnection() throws Exception { connection.close(); } @Test public void testCurrentDateNotNull() throws Exception { // Execute a query to retrieve the current date from the database Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT CURRENT_DATE"); // Verify that the result set is not null assertNotNull(resultSet); // Move the cursor to the first row resultSet.next(); // Retrieve the current date value from the result set LocalDate currentDate = resultSet.getObject(1, LocalDate.class); System.out.println("Date is " + currentDate); // Verify that the current date is not null assertNotNull(currentDate); } }
As you can see, the code is much leaner as we reference the org.testcontainers.containers.PostgreSQLContainer which provides details about the JDBC Connection so that we can run a simple Test with it.
Run the above Test in your IDE and verify that the current Data is not null:

Conclusion
In this tutorial, we explored how to use Testcontainers to set up a GenericContainer
and a PostgreSQL container for your Java tests. We learned how to include Testcontainers as a dependency, start and stop containers, and perform tests using the containerized dependencies. Testcontainers is a powerful library that simplifies testing by providing disposable containers for your dependencies, enabling you to write more reliable and isolated tests.
By utilizing Testcontainers in your Java tests, you can ensure that your applications are thoroughly tested against real dependencies, leading to more robust and reliable software.
Source code for this article: https://github.com/fmarchioni/mastertheboss/tree/master/test/testcontainer