Appearance
Fresh
Lifecycle callbacks
Back
Testcontainers container lifecycle management using JUnit 5
Learn different approaches to manage container lifecycle with Testcontainers using JUnit 5 lifecycle callbacks, extension annotations, and the singleton containers pattern.
Java Testing with Docker
20 minutes
JUnit 5 lifecycle callbacks
Copy as Markdown
Open MarkdownAsk Docs AIClaudeOpen in Claude
When testing with Testcontainers, you want to start the required containers before executing any tests and remove them afterwards. You can use JUnit 5 @BeforeAll and @AfterAll lifecycle callback methods for this:
java
package com.testcontainers.demo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.postgresql.PostgreSQLContainer;
class CustomerServiceWithLifeCycleCallbacksTest {
static PostgreSQLContainer postgres = new PostgreSQLContainer(
"postgres:16-alpine"
);
CustomerService customerService;
@BeforeAll
static void startContainers() {
postgres.start();
}
@AfterAll
static void stopContainers() {
postgres.stop();
}
@BeforeEach
void setUp() {
customerService =
new CustomerService(
postgres.getJdbcUrl(),
postgres.getUsername(),
postgres.getPassword()
);
customerService.deleteAllCustomers();
}
@Test
void shouldCreateCustomer() {
customerService.createCustomer(new Customer(1L, "George"));
Optional<Customer> customer = customerService.getCustomer(1L);
assertTrue(customer.isPresent());
assertEquals(1L, customer.get().id());
assertEquals("George", customer.get().name());
}
@Test
void shouldGetCustomers() {
customerService.createCustomer(new Customer(1L, "George"));
customerService.createCustomer(new Customer(2L, "John"));
List<Customer> customers = customerService.getAllCustomers();
assertEquals(2, customers.size());
}
}Here's what the code does:
PostgreSQLContaineris declared as a static field. The container starts before all tests and stops after all tests in this class.@BeforeAllstarts the container,@AfterAllstops it.@BeforeEachinitializesCustomerServicewith the container's JDBC parameters and deletes all rows to give each test a clean database.
Key observations:
- Because the container is a static field, it's shared across all test methods in the class. You can declare it as a non-static field and use
@BeforeEach/@AfterEachto start a new container per test, but this isn't recommended as it's resource-intensive. - Even without explicitly stopping the container in
@AfterAll, Testcontainers uses the Ryuk container to clean up containers automatically when the JVM exits.