I'm experiencing a persistent timeout issue with my Jest tests for an Express.js application using MongoDB Memory Server. The test appears to be successful (receiving a 200 status code) but Jest times out before completing, showing the error
"Cannot log after tests are done. Did you forget to wait for something async in your test?"
Here's the specific error output:
FAIL tests/post.controller.test.ts (14.057 s) ● Console console.log Starting ... at tests/post.controller.test.ts:6:13
● Post Controller › GET /posts should return a list of posts thrown: "Exceeded timeout of 10000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test."
● Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Awaiting ..: 200". The test is making a request to /posts endpoint which connects to MongoDB, but Jest detects an open handle (TCPSERVERWRAP) that prevents it from exiting cleanly.
My Setup Test file (tests/post.controller.test.ts): typescript
import request from 'supertest';
import app from '../src/app';
describe("Post Controller", () => {
it("GET /posts should return a list of posts", async () => {
console.log("Starting ...");
const response = await request(app).get("/posts");
console.log("Awaiting ..:", response.status);
expect(response.status).toBe(200);
expect(Array.isArray(response.body)).toBe(true);
}, 10000);
});
Jest config (jest.config.js): javascript
export default {
preset: "ts-jest",
testEnvironment: "node",
setupFiles: ["dotenv/config"],
collectCoverage: true,
coverageReporters: ["text", "html"],
coverageDirectory: "<rootDir>/coverage/",
setupFilesAfterEnv: ["<rootDir>/tests/setup.ts"],
forceExit: true,
detectOpenHandles: true,
};
Database setup (tests/db.ts): typescript
import mongoose from "mongoose";
import { MongoMemoryServer } from "mongodb-memory-server";
let mongod: MongoMemoryServer;
export const connect = async () => {
if (mongoose.connection.readyState !== 0) {
await mongoose.disconnect();
}
mongod = await MongoMemoryServer.create();
const uri = mongod.getUri();
await mongoose.connect(uri);
};
export const closeDatabase = async () => {
if (mongoose.connection.readyState !== 0) {
await mongoose.connection.dropDatabase();
await mongoose.connection.close();
}
if (mongod) {
await mongod.stop();
}
};
Express app (src/app.ts): typescript
import express, { Express } from "express";
import router from "./routes/routes";
const app: Express = express();
app.use(express.json());
app.use("/", router);
export default app;
What I tried:
Increased the test timeout from 5000ms to 10000ms Added forceExit: true and detectOpenHandles: true to Jest config Added console.log statements to track test execution Created a database helper with MongoDB Memory Server for testing
What I expected:
The test should complete successfully within the timeout period Jest should exit cleanly without detecting open handles The database connection should be properly managed during testing
What actually happened:
The test receives a 200 response (visible in logs) but still times out Jest shows "Cannot log after tests are done" error An open TCPSERVERWRAP handle is detected, preventing clean exit The MongoDB Memory Server connection setup in tests/db.ts doesn't seem to be properly integrated with the test lifecycle
Questions
- How can I properly integrate MongoDB Memory Server with Jest test lifecycle?
- Why is the test timing out even though it appears to complete successfully?
- How do I ensure the database connection is properly closed after tests to avoid the open handle issue?
- Is there a better pattern for testing Express apps with MongoDB using Jest?
Environment
- Node.js version: Latest
- Jest version: Latest
- MongoDB Memory Server
- Express.js
- TypeScript
- Supertest for HTTP testing