Problem
Starting November 10th, my Jest integration tests began failing randomly with MongoDB connection errors. The tests use @testcontainers/mongodb v11.5.1 and mongodb v8.0.12.
Error:
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
at Timeout._onTimeout (node_modules/mongodb/src/sdam/topology.ts:591:30)
The failures are intermittent - sometimes all tests pass, sometimes a fair amount (20-50) fail with this connection error. If I run a single test file, the error might pop up there too.
● Product Import Integration Tests › Product Updates › Variable Products › Variation Creation › should create variations with correct SKUs
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:20017
at Timeout._onTimeout (node_modules/mongodb/src/sdam/topology.ts:591:30)
● Product Import Integration Tests › Product Updates › Variable Products › Variation Creation › should create variations with correct SKUs
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:20017
at Timeout._onTimeout (node_modules/mongodb/src/sdam/topology.ts:591:30)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 52 passed, 53 total
Snapshots: 0 total
Time: 55.721 s, estimated 65 s
Setup
Jest Configuration:
const config: Config = {
globalSetup: "<rootDir>/tests/globalSetup.ts",
globalTeardown: "<rootDir>/tests/globalTeardown.ts",
projects: [
{
displayName: "integration",
testEnvironment: "node",
testMatch: ["<rootDir>/tests/integration/**/*.integration.test.ts"],
setupFilesAfterEnv: ["<rootDir>/tests/integration/integrationSetup.ts"],
testTimeout: 15000,
},
],
};
globalSetup.ts (starts one shared MongoDB container):
import { MongoDBContainer } from "@testcontainers/mongodb";
import type { StartedMongoDBContainer } from "@testcontainers/mongodb";
declare global {
var __MONGO_CONTAINER__: StartedMongoDBContainer | undefined;
}
export default async function globalSetup() {
const mongoContainer = await new MongoDBContainer("mongo:8.0.12").start();
global.__MONGO_CONTAINER__ = mongoContainer;
process.env.MONGO_CONTAINER_URI = mongoContainer.getConnectionString();
}
integrationSetup.ts (runs per worker, creates isolated databases):
beforeAll(async () => {
const baseMongoUri = process.env.MONGO_CONTAINER_URI;
if (!baseMongoUri) {
throw new Error("MongoDB container URI not found");
}
// Each worker gets its own database
const workerId = process.env.JEST_WORKER_ID || "1";
const dbName = `test-db-${workerId}`;
const mongoUri = `${baseMongoUri}/${dbName}`;
process.env.MONGODB_URI = mongoUri;
await mongoose.connect(mongoUri, { directConnection: true });
}, 60000);
afterAll(async () => {
if (mongoose.connection.readyState === 1) {
await mongoose.connection.db.dropDatabase();
await mongoose.disconnect();
}
});
afterEach(async () => {
if (mongoose.connection.readyState === 1 && mongoose.connection.db) {
const collections = await mongoose.connection.db.collections();
for (const collection of collections) {
await collection.deleteMany({});
}
}
});
Env Configuration env.ts
import zennv from "zennv";
import dotenv from "dotenv";
import z from "zod";
// Load appropriate .env file based on NODE_ENV
// zennv uses dotenv under the hood, so we can load it here
// to ensure the environment variables are available before zennv processes them.
// https://github.com/tomanagle/zennv
// Only load dotenv if it hasn't been loaded already
if (!process.env.DOTENV_LOADED) {
if (process.env.NODE_ENV === "test") {
dotenv.config({ path: ".env.test", override: false });
} else {
dotenv.config({ override: false });
}
process.env.DOTENV_LOADED = "true";
}
export const env = zennv({
dotenv: false, // We've already loaded dotenv
schema: z.object({
MONGODB_URI: z.string().default("mongodb://localhost:27017"),
}),
});
What I've Tried
I changed the MongoDB port in .env.test from 27017 to 20017 to verify which configuration was being used. The error then showed ECONNREFUSED 127.0.0.1:20017, confirming that in some cases, tests are using the .env.test value instead of the dynamically set MONGODB_URI from the testcontainer.
This suggests that either:
- Some tests start before
globalSetupcompletes, or - Some workers don't receive the updated
process.env.MONGODB_URI
Question
How can I ensure that all Jest workers reliably receive the MongoDB URI from integrationSetup before any tests execute?
Is there a race condition in my setup where parallel workers might start running tests before the environment variable is propagated? Should I be using a different mechanism to share the db connection string across workers?
Environment
- Node.js v22.18.0
- Jest v30.1.2