You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Jest测试中mongoose.connect遗留openHandles的问题

问题核心原因

你遇到的openHandles问题本质是Jest的生命周期钩子没有等待异步操作完全执行完毕就进入了下一阶段,导致数据库连接建立、断开的操作没有完整跑完,留下了未释放的TLS连接句柄。你虽然写了connect和disconnect逻辑,但Jest没有等待这些异步操作完成就执行后续步骤,因此断开逻辑可能在连接还没完全建立的时候就执行了,无法正确清理所有句柄。

解决步骤

  • 修正Jest异步钩子的写法,强制等待所有异步操作执行完成
    把beforeAll、afterAll以及测试用例中的异步逻辑都加上async/await,确保Jest等待异步操作执行完成再推进生命周期,修正后的测试代码如下:
    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(async () => {
        try {
          await startTestDB()
          console.log("Connected to db.");
        } catch (e) {
          console.log(e);
        }
      });
    
      afterAll(async () => {
        try {
          await mongoose.disconnect()
          console.log('db connection is closed');
        } catch (e) {
          console.error(e);
        }
      });
    
      it("Should save a new user", async () => {
        await request(app)
          .post("/save")
          .send({
            name: faker.internet.userName(),
            email: faker.internet.email()
          })
          .expect(201);
      });
    });
    
  • 优化mongoose连接配置,降低句柄残留概率
    如果你使用的是MongoDB Atlas的srv连接串,可以在mongoose.connect的配置项中添加以下参数,避免TLS连接残留:
    mongoose.connect(
      `mongodb+srv://${mongodb.user}:${mongodb.password}@${mongodb.host}/${mongodb.db}-test?retryWrites=true&w=majority`,
      {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        family: 4, // 强制使用IPv4解析,避免IPv6解析导致的TLS连接残留
        poolSize: 1, // 测试环境仅保留1个连接,减少句柄生成
        autoReconnect: false, // 测试场景不需要自动重连
        connectTimeoutMS: 10000
      }
    )
    
  • 多测试文件场景统一管理数据库连接
    如果项目中有多个测试文件都需要连接数据库,不要在每个文件单独处理连接和断开,而是在jest.config.js中配置setupFilesAfterEnv,全局统一在所有测试启动前建立连接,所有测试结束后断开连接,避免频繁建立断开连接产生的残留句柄。
  • 优先使用本地内存数据库做单元测试
    可使用mongodb-memory-server启动本地内存MongoDB实例进行测试,不需要走远程网络TLS连接,从根源上避免TLSWRAP类型的句柄残留,同时测试运行速度也会更快。

注意:如果完成以上修改后仍有openHandles提示,可检查是否有其他位置调用了mongoose.connect未被正确关闭,或者项目中是否存在未清理的全局定时器、未结束的网络请求。

内容的提问来源于stack exchange,提问作者Mohamed abdelmagid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:48:03