Node.js单元测试出现MongoNotConnectedError问题求助
解决Node.js中co/yield配合单元测试的Mongo连接问题
问题场景
业务代码(使用co和yield):
module.exports = { moduleName(payload, callback){ // first logic // second logic co(function*(){ yield user.findById(somerandomid) // error when find user by id }) } }
单元测试代码:
beforeAll(async () => { await dbHandler.connect(); // 连接mongodb }); afterAll(async () => { await dbHandler.disconnect(); }); afterEach(async () => { jest.clearAllMocks(); }); it("test",()=>{ moduleName(somepayload) })
运行测试时出现错误:
MongoNotConnectedError: Client must be connected before running operations
尝试在测试用例中用co包裹连接和函数调用,但问题未解决:
it('ts',async()=>{ co(function*(){ yield dbHandler.connect() yield moduleName(somepayload) }) })
可行解决思路
1. 修复业务代码的异步逻辑暴露问题
你的moduleName函数里调用了co,但没有把这个异步操作的结果传递出来——不管是返回Promise还是通过callback回调,测试用例都无法感知到异步操作何时完成,导致数据库查询可能在连接就绪前就执行了。
- 改成返回Promise的形式:
module.exports = { moduleName(payload) { // first logic // second logic return co(function*(){ return yield user.findById(somerandomid); }); } }
- 如果要保留callback:
module.exports = { moduleName(payload, callback){ // first logic // second logic co(function*(){ const result = yield user.findById(somerandomid); callback(null, result); // 成功时传递结果 }).catch(err => { callback(err); // 捕获错误并传递 }); } }
2. 测试用例必须等待异步操作完成
Jest不会自动等待异步代码执行,必须显式告知测试何时结束:
- 若业务代码返回Promise,用
async/await:
it("test", async () => { await moduleName(somepayload); // 这里可以加断言 });
- 若用callback,使用Jest的
done回调:
it("test", (done) => { moduleName(somepayload, (err, result) => { if (err) throw err; // 可添加断言 done(); // 告知Jest测试完成 }); });
3. 确认dbHandler.connect()的连接逻辑正确
检查dbHandler.connect()的实现,确保它是真正的异步函数,只有当数据库连接完全建立后才会resolve。比如使用mongoose时:
// dbHandler.connect()的正确示例 async function connect() { await mongoose.connect(process.env.MONGO_URI, { // 必要的连接选项 }); }
避免出现连接逻辑里有异步操作却未await的情况,导致beforeAll中的await dbHandler.connect()提前执行完毕,但实际数据库还没连上。
4. 不要在测试用例中重复调用连接
beforeAll已经完成了数据库连接,测试用例里再次调用dbHandler.connect()会导致重复连接,反而可能引发问题,直接复用beforeAll建立好的连接即可。
内容的提问来源于stack exchange,提问作者bramasta vikana
相关产品推荐
相关产品推荐

