使用Chai测试Express异步路由失败问题求助
解决Chai+Mocha测试Express异步路由超时问题
我仔细看了你的测试代码、路由逻辑和报错信息,发现两个核心问题导致了测试超时,咱们一步步来解决:
问题根源分析
1. 路由代码里的低级拼写错误
你的路由里有个笔误:res.sendStatu(400)(少了最后一个s),正确的Express响应方法是res.sendStatus()。这个错误会直接同步抛出异常,但这个异常不在user.login_user()的Promise链范围内,所以不会被你写的.catch(err => { ... })捕获。Express会把这个异常传给默认错误处理中间件,但这个过程会导致请求没有正常返回响应,测试里的Chai请求一直挂着等结果,最终触发超时。
2. 测试代码混用Promise与done()
你在测试里同时用了Promise的.then()/.catch()和Mocha的done()回调,而且在catch里直接throw err——这会导致如果请求出错,错误没有被Mocha捕获,也不会调用done(),Mocha就会一直等待直到超时。另外,你的测试断言也写错了:根据路由逻辑,空请求体应该返回400,而不是200,这也会导致测试失败。
解决方案
第一步:修复路由代码的拼写错误
把所有的res.sendStatu()改成res.sendStatus(),同时推荐用async/await的try/catch替代Promise链,代码更简洁易读:
router.post('/', async function(req, res, next) { try { if (!req.body) return res.sendStatus(400); if (!req.body.usr) return res.sendStatus(400); if (!req.body.psw) return res.sendStatus(400); let user = new _USER(); const ret = await user.login_user(req.body.usr, req.body.psw); if (ret === false) { return res.sendStatus(401); } req.session.active = true; req.session.user = ret; res.sendStatus(200); } catch (err) { _UTILS.errorHandler(err, false, true); res.sendStatus(500); } });
第二步:修正测试代码的写法
不要混用done()和Promise,优先直接返回Promise(Mocha会自动处理Promise的resolve/reject),同时修正断言的状态码:
describe('/Login wrong user', () => { it('It should return 400 when login POST has no data', () => { // 直接返回Promise,Mocha会自动等待它完成 return chai.request(app) .post('/login') .send({}) .then((res) => { expect(res).to.have.status(400); }); }); });
如果一定要用done()写法,记得在catch里把错误传给done():
describe('/Login wrong user', () => { it('It should return 400 when login POST has no data', (done) => { chai.request(app) .post('/login') .send({}) .then((res) => { expect(res).to.have.status(400); done(); }) .catch((err) => { done(err); // 把错误传递给Mocha处理 }); }); });
额外小提示
- 测试前确保Express的全局错误处理中间件配置正确,避免未捕获的异常导致请求挂起;
- 异步测试优先用返回Promise的写法,代码更简洁,不容易踩回调陷阱;
- 写路由时注意方法名拼写,这类低级错误很容易引发奇怪的超时/无响应问题。
内容的提问来源于stack exchange,提问作者NashPL
相关产品推荐
相关产品推荐

