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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:04:35