Java Tests "Connection refused" to Test DB in CI - Fix Connectivity
A Connection refused to a test database means nothing was listening at that host:port when the test connected - the DB service had not finished starting, was on a different host/port, or was not started at all. Service-container startup races are a frequent transient cause.
What this error means
A test fails with java.net.ConnectException: Connection refused while opening a JDBC connection (e.g. to localhost:5432). Often the DB service container is still booting when the first test connects.
Caused by: java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.connect0(Native Method)
org.postgresql.util.PSQLException: Connection to localhost:5432 refused.
Check that the hostname and port are correct and the server is accepting TCP/IP connections.Common causes
Database not ready when tests started
A services: DB container (or a separately launched DB) accepts connections only after it finishes initializing; tests that connect first get "Connection refused" (transient).
Wrong host/port or DB not started
The JDBC URL points at the wrong host/port, or the DB was never started in CI, so the refusal is deterministic until fixed.
How to fix it
Wait for the DB to be healthy before tests
Gate tests on a health check so they only run once the DB accepts connections.
services:
postgres:
image: postgres:16
env: { POSTGRES_PASSWORD: test }
ports: ['5432:5432']
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s --health-timeout 5s --health-retries 10Verify the JDBC target
- Confirm the JDBC URL host/port match the service mapping (e.g.
localhost:5432). - For flaky readiness, prefer Testcontainers, which waits for the DB before returning the URL.
- Add a brief connection retry in test setup for service-container races.
How to prevent it
- Gate tests on a DB health check (or use Testcontainers), and keep the JDBC URL in sync with the service mapping so connectivity is deterministic.