API运行正常但MongoDB单测无理由报MongoClient未连接如何解决?
问题根因
你遇到的是测试运行时的单例Mongo连接状态冲突问题,核心触发逻辑如下:
- 你的MongoHelper是全局单例,jest默认会并行执行多个测试文件,其他测试文件的
afterAll会先于当前测试的用例执行,调用disconnect关闭连接,导致当前测试用到的客户端连接被提前销毁 - 你当前测试的
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
相关产品推荐
相关产品推荐

