How to Set Up Testcontainers for Java and JUnit in CI
GitHub-hosted Linux runners ship Docker, so a JUnit 5 test annotated with @Testcontainers runs in CI with no extra service setup.
Add the testcontainers and junit-jupiter dependencies, annotate the test class with @Testcontainers, and mark each container field @Container. The extension starts containers before tests and stops them after.
Steps
- Add
org.testcontainers:junit-jupiter(and a module likepostgresql) as a test dependency. - Annotate the class
@Testcontainersand each container field@Container. - Read the mapped host/port from the running container in your test.
- Run on
ubuntu-latest; Docker is already present on GitHub-hosted runners.
Test class
OrderRepositoryTest.java
@Testcontainers
class OrderRepositoryTest {
@Container
static PostgreSQLContainer<?> db =
new PostgreSQLContainer<>("postgres:16-alpine");
@Test
void savesOrder() {
String url = db.getJdbcUrl();
// connect with db.getUsername() / db.getPassword()
assertThat(url).startsWith("jdbc:postgresql://");
}
}Workflow
.github/workflows/ci.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven
- run: mvn -B verifyGotchas
- A
static@Container starts once per class; a non-static one restarts per test method. - The Docker requirement is met on GitHub-hosted Linux runners; Windows and macOS runners do not ship a usable Docker daemon.
Related guides
How to Meet the Docker Requirement for Testcontainers in CITestcontainers needs a working Docker daemon; GitHub-hosted Linux runners already provide one, so verify it w…
How to Run a Postgres Container for Tests With Testcontainers in CIStart a throwaway PostgreSQL container with Testcontainers in CI, reading the mapped JDBC URL, username, and…
How to Control Container Lifecycle: Per-Class vs Per-MethodDecide whether a Testcontainers container starts once per test class or restarts per test method, trading iso…