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

使用Mocha+Supertest+Chai测试时遇done()传入非Error问题求助

解决Mocha+Supertest+Chai中done() invoked with non-Error错误指南

我太懂这种明明请求跑通了,但测试死活不通过的憋屈感了!你遇到的这个done() invoked with non-Error: {"req":{ …} request done without error, but test didn't pass错误,本质是Mocha异步测试的回调逻辑没处理对,结合你用的技术栈,我给你梳理几个核心排查方向和解决办法:

1. 别给done()传非错误参数

Mocha的done()回调规则很严格:要么不传参数(表示测试通过),要么只传Error类型对象。如果你不小心把响应对象、字符串之类的值传给它,就会触发这个错误。

❌ 错误示例:

api.get('/your-endpoint')
  .end((err, res) => {
    // 错误:把res传给了done()
    done(res); 
  });

✅ 正确写法:

api.get('/your-endpoint')
  .end((err, res) => {
    if (err) return done(err); // 只有出错时才传错误对象
    // 这里写你的断言逻辑
    res.status.should.equal(200);
    done(); // 无参数调用,告诉Mocha测试完成且通过
  });

2. 确保断言逻辑没“隐身失败”

有时候请求成功了,但断言写错了(比如断言的字段不存在、状态码不匹配),但你没让Mocha捕获到这个错误,也会导致测试卡壳。Chai的should/expect断言失败时会抛出错误,只要别用try/catch把错误吞掉,Mocha就能自动识别测试失败:

api.get('/your-endpoint')
  .end((err, res) => {
    if (err) return done(err);
    // 直接写断言,失败时会自动抛出错误,Mocha会捕获
    expect(res.body.data).to.be.an('array');
    res.should.have.property('message', 'request success');
    done();
  });

3. 换Async/Await写法彻底告别done()

如果你觉得回调逻辑容易搞混,Supertest支持Promise,配合Mocha的Async/Await写法会清爽很多,完全不用管done():

it('should fetch data successfully', async () => {
  const res = await api.get('/your-endpoint');
  // 直接写断言,出错时Mocha会自动捕获
  res.status.should.equal(200);
  expect(res.body).to.have.property('code', 0);
});

这种写法下,只要断言不失败,测试就会自动通过;如果请求出错或者断言失败,Mocha会直接标记测试失败,不会出现done()相关的奇怪错误。

4. 排查隐藏的未处理Promise拒绝

有时候你的业务代码里可能有其他异步操作(比如数据库查询、内部API调用)没处理好,导致Promise被拒绝但没被捕获,也会间接触发这个错误。可以在测试文件开头加一段代码,帮你揪出隐藏的异步错误:

process.on('unhandledRejection', (err) => {
  console.error('发现未处理的Promise拒绝:', err);
  throw err;
});

内容的提问来源于stack exchange,提问作者Viktorija Filipov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:55:55