使用Jest/mongodb-memory-server测试API出现setTimeout及连接报错
根因说明
你遇到的超时报错只是表象,核心错误是下面这个Mongoose连接冲突:
MongooseError: Can't call
openUri()on an active connection with different connection strings.
触发原因是你测试API时,supertest启动的应用本身已经执行了一次Mongoose连接初始化(比如应用入口自带的数据库连接逻辑),同时测试文件的beforeAll钩子又调用了db.connect去连接mongodb-memory-server的实例,两次连接用了不同的URI导致冲突,后续的钩子逻辑卡壳才触发超时,单纯调高超时阈值无法解决问题。
解决方案
- 第一步:隔离测试环境的应用连接逻辑
在应用的数据库初始化代码处加环境判断,测试环境下不要让应用自行初始化数据库连接,统一使用测试用的db模块管理连接:
// 应用原有的数据库连接逻辑处添加判断 if (process.env.NODE_ENV !== 'test') { // 原有的mongoose.connect初始化代码 }
- 第二步:优化测试db模块的连接逻辑
修改Tests/db.js的connect方法,先判断当前是否有活跃连接,避免重复调用连接方法:
module.exports.connect = async () => { // readyState为0表示未连接,非0状态直接跳过连接逻辑 if (mongoose.connection.readyState !== 0) { return } const uri = await mongod.getUri() // mongod为你初始化的MongoMemoryServer实例 const mongooseOpts = { useNewUrlParser: true, useUnifiedTopology: true, }; await mongoose.connect(uri, mongooseOpts); };
- 第三步:补全数据库清理、关闭逻辑
确保clearDatabase只清理集合数据不关闭连接,closeDatabase要同时断开Mongoose连接和停止mongodb-memory-server实例:
// 清理数据逻辑 module.exports.clearDatabase = async () => { const collections = mongoose.connection.collections for (const key in collections) { await collections[key].deleteMany({}) } } // 关闭连接逻辑 module.exports.closeDatabase = async () => { await mongoose.connection.dropDatabase() await mongoose.connection.close() await mongod.stop() // 停止内存数据库实例 }
- 第四步(可选):处理多测试文件并行冲突
如果存在多个测试文件都用到内存数据库,可在jest.config.js中添加配置让测试串行执行,避免多实例连接冲突:
// jest.config.js module.exports = { // 其他配置 maxWorkers: 1 }
如果测试跑完后仍提示Jest未正常退出,可在启动命令中添加--forceExit参数强制退出。
内容的提问来源于stack exchange,提问作者jeyremd
相关产品推荐
相关产品推荐

