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

API运行正常但MongoDB单测无理由报MongoClient未连接如何解决?

问题根因

你遇到的是测试运行时的单例Mongo连接状态冲突问题,核心触发逻辑如下:

  1. 你的MongoHelper是全局单例,jest默认会并行执行多个测试文件,其他测试文件的afterAll会先于当前测试的用例执行,调用disconnect关闭连接,导致当前测试用到的客户端连接被提前销毁
  2. 你当前测试的userCollection是在beforeAll阶段一次性缓存的,后续连接被重置后没有更新引用,自然会抛出MongoClient must be connected的报错

API运行正常是因为开发/生产环境不会频繁创建销毁Mongo连接,只有测试环境会在每个测试套件结束后断开连接,才会触发这个问题。

修复方案

  • 首先调整测试代码的集合获取逻辑,不要在beforeAll里缓存集合实例,每次要用的时候再从MongoHelper获取:
describe('POST /signup', () => {
  beforeAll(async () => {
    await MongoHelper.connect(global.__MONGO_URI__)
    app.post('/api/auth/signup', signUpController)
  })

  afterAll(async () => {
    await MongoHelper.disconnect()
  })

  afterEach(async () => {
    // 每次获取最新的集合实例
    const userCollection = MongoHelper.getCollection('users')
    await userCollection.deleteMany({})
  })

  const agent = request.agent(app)

  it('Should return 200 if all validations succeds', async () => {
    await agent.post('/api/auth/signup').send(makeFakeSignUpUserCredentials()).expect(200)
  })
})
  • 其次给测试配置串行执行,避免多文件并行时单例状态互相影响。如果你用的是jest,可以在jest.config.js里加maxWorkers: 1强制单线程执行测试,彻底解决并行冲突问题
  • 可选优化:给MongoHelper加连接状态判断,避免无效操作:
export const MongoHelper = {
  client: null as MongoClient | null,
  async connect (url: string): Promise<void> {
    // 已经连接就不要重复创建实例
    if (this.client?.isConnected()) return
    this.client = await MongoClient.connect(url)
  },

  async disconnect (): Promise<void> {
    if (!this.client) return
    await this.client.close()
    this.client = null
  },

  getCollection (name: Collections): Collection {
    if (!this.client?.isConnected()) throw new Error('MongoClient not connected')
    return this.client.db().collection(name)
  }
}

内容的提问来源于stack exchange,提问作者Christian Gama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 18:06:01