Testcontainers and e2e on Jenkins with Java

TL;DR - Testcontainers spins up Postgres, Redis and whatever else you need in the pipeline; you test against real dependencies. In CI, unit tests first and containers in a separate stage: fast feedback and real confidence.


I wanted the Java pipeline tests to run against real dependencies (DB, cache, queues) without relying on a shared environment everyone steps on. Testcontainers fits that: it starts Docker containers at test time and tears them down at the end. No single Postgres instance on the CI server.

flowchart TB
  Jenkins[Jenkins] --> Build[Build Java]
  Build --> Unit[Unit tests]
  Unit --> TC[Testcontainers]
  TC --> Docker[Docker]
  Docker --> DB[(Postgres/Redis)]
  TC --> E2E[E2E]
  E2E --> API[Real API]

On Jenkins the executor needs Docker (or access to the socket). Maven/Gradle starts the containers in the test phase; each module or suite declares what it needs. With JUnit 5 and Postgres: annotate the class with @Testcontainers, define the container with @Container and the test uses the URL Testcontainers injects. For e2e it’s the same idea: bring up the API, the DB and if it makes sense a message broker; the test sends requests and validates the full flow.

The cost is time. Container tests take longer than pure unit tests. In CI I split: unit tests always first; Testcontainers and e2e in a later stage (or in parallel), and failure there blocks merge. The developer doesn’t wait for containers to start on every commit, but nothing ships without passing those tests.

In practice the tests ran daily in staging via Jenkins after changes landed on the release branch. When something failed I added a regression test right after the fix. That way the same bug didn’t come back and the e2e suite kept getting more representative of what actually matters in production.