Mohamed abdelmagid
Mohamed abdelmagid

Reputation: 379

mongoose.connect leaves open handles after jest test

How to get rid of the openHandles left by mongoose.connect in jest test

const { startTestDB } = require("../conn");
const mongoose = require("mongoose");
const request = require("supertest");
const faker = require("faker");
const app = require("../app");
const fs = require("fs");

describe("test1: ", () => {
  beforeAll(() => {
    startTestDB()
      .then(() => {
        console.log("Connected to db.");
      })
      .catch((e) => {
        console.log(e);
      });
  });

  afterAll(() => {
    mongoose
      .disconnect()
      .then(() => {
        console.log('db connection is closed');
      })
      .catch((e) => {
        console.error(e);
      });
  });

  it("Should save a new user", async () =>
    request(app)
      .post("/save")
      .send({
        name: faker.internet.userName(),
        email: faker.internet.email()
      })
      .expect(201));
});

This is an example code that has the same problem, when I run npx jest --detectOpenHandles I find one at mongoose.connect, as per my knowledge open handles occur because of async operations that didn't finish before tests, but I clearly close the connection in afterAll.

The Error Message I got:

  ●  TLSWRAP

       9 |
      10 | module.exports.startTestDB = () =>
    > 11 |   mongoose.connect(
         |            ^
      12 |     `mongodb+srv://${mongodb.user}:${mongodb.password}@${mongodb.host}/${mongodb.db}-test?retryWrites=true&w=majority`,
      13 |     {
      14 |       useNewUrlParser: true,

      at parseSrvConnectionString (node_modules/mongodb/lib/core/uri_parser.js:67:7)
      at parseConnectionString (node_modules/mongodb/lib/core/uri_parser.js:597:12)
      at connect (node_modules/mongodb/lib/operations/connect.js:282:3)
      at node_modules/mongodb/lib/mongo_client.js:260:5
      at maybePromise (node_modules/mongodb/lib/utils.js:692:3)
      at MongoClient.Object.<anonymous>.MongoClient.connect (node_modules/mongodb/lib/mongo_client.js:256:10)
      at node_modules/mongoose/lib/connection.js:835:12
      at NativeConnection.Object.<anonymous>.Connection.openUri (node_modules/mongoose/lib/connection.js:832:19)
      at node_modules/mongoose/lib/index.js:351:10
      at node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5
      at promiseOrCallback (node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)
      at Mongoose.Object.<anonymous>.Mongoose._promiseOrCallback (node_modules/mongoose/lib/index.js:1149:10)
      at Mongoose.connect (node_modules/mongoose/lib/index.js:350:20)
      at startTestDB (conn.js:11:12)
      at tests/s.test.js:10:5
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:387:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:408:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:261:3)

Upvotes: 4

Views: 1191

Answers (2)

Fiehra
Fiehra

Reputation: 807

I am reposting my answer from this question jest and mongoose - jest has detected opened handles as this was my solution for the problem.

closing the connection as many others have proposed did not work for me.

after many hours of searching for a solution on SO and github issues, I came across this github thread https://github.com/visionmedia/supertest/issues/520 with multiple solutions offered. what was finally working for me was implementing a global-teardown-file in my root directory like so:

// test-teardown-globals.js
module.exports = () => {
  process.exit(0);
};

and also by adjusting my jest.config.js slightly

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  globalTeardown: '<rootDir>/test-teardown-globals.js',
};

UPDATE: although this works this solution is only viable for developing and running tests locally. I also prefer Özgür Atmaca's solution by disconnecting before reconnecting in the beforeAll block

Upvotes: 5

Liger
Liger

Reputation: 191

I am too reposting my answer here: https://stackoverflow.com/a/73673449/4012944

Mongoose web site clearly does not recommend using Jest with Mongoose apps and does not recommend timers or global setups/teardowns.

Such workaround feels more natural to me.

beforeAll(async () => {
  await mongoose.disconnect();
  await mongoose.connect(MONGODB_URL, MONGODB_OPTIONS);
});

Hope it helps!

Upvotes: 3

Related Questions