Mocha测试Express异步中间件时done函数失效问题排查
解决Mocha测试异步认证中间件时提前结束的问题
我明白你遇到的困扰了——Mocha测试总在jwt.verify的异步回调执行前就跑完,导致断言结果不符合预期对吧?这其实是时序匹配错误,咱们一步步拆解问题和解决办法:
问题根源
你当前的测试把Mocha的done直接传给了中间件的next参数,然后立刻执行expect断言。但jwt.verify是异步操作,它的回调要等一会儿才会触发next()(也就是你传的done)。这就导致断言在res.status(401)被调用前就执行了,测试自然会提前结束,结果也不对。
另外,直接把done当next用本身就不合理:Mocha的done是用来通知测试"异步操作完成"的信号,而非中间件的next逻辑本身,时序上完全不匹配。
修复方案
我们需要调整测试逻辑,让断言等异步操作完成后再执行,同时正确触发Mocha的done信号。具体改法如下:
修改后的测试代码
describe("AuthMiddleware", () => { it("Should return 401 if token is expired", (done) => { const options = { headers: { authorization: "Bearer " + expiredToken } } const req = mockReq(options) as Request const res = mockRes() as Response // 自定义next函数,把断言和done逻辑放在这里 const customNext = () => { // 等中间件的异步操作完成后,再执行断言 expect(res.status).to.have.been.calledWith(401) // 通知Mocha测试全部完成 done() } // 把自定义的next传给中间件 AuthMiddleware(req, res, customNext) }).timeout(10000) })
为什么这样有效?
- 中间件里的
jwt.verify异步回调执行完毕后,才会调用customNext,这时候res.status(401)已经被触发,断言能拿到正确的结果。 done()放在customNext最后,确保Mocha会一直等待,直到异步操作完成、断言执行完毕后才结束测试。
额外提示
顺便提一下你的中间件逻辑:当前代码只处理了token不存在和token验证失败的情况,token验证成功时没有任何处理(比如把解码后的token挂载到req上再调用next),如果后续业务需要,记得补充这部分逻辑哦。
内容的提问来源于stack exchange,提问作者Mike Hawkins
相关产品推荐
相关产品推荐

