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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:35:22