使用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
相关产品推荐
相关产品推荐

