Chai测试无法通过Cookie认证中间件 运行报sendStatus未定义错误
认证中间件挂载后测试报错排查与修复
问题复现表现
- 路由未挂载认证中间件时,Chai+chai-http编写的测试用例可正常运行,返回200状态通过校验
- 只要将
authenticate中间件加入路由执行链路,测试直接报错失败 - 抛出的具体错误堆栈:
TypeError: Cannot read property 'sendStatus' of undefined
at /Users/myname/Desktop/Code/myapp/server/src/middleware/authenticate.ts:21:29
at Object.module.exports [as verify] (/Users/myname/Desktop/Code/myapp/server/node_modules/jsonwebtoken/verify.js:57:12)
问题核心根因
所有报错均来自认证中间件的代码逻辑错误,和测试框架本身无关,具体问题点:
- 变量作用域覆盖冲突:
jwt.verify方法的回调形参直接命名为res,覆盖了外层作用域中Express的响应对象res。当JWT校验失败进入错误分支时,回调里的res实际指向JWT解码的用户载荷,在存在校验错误的场景下该值为undefined,调用res.sendStatus就会触发读取undefined属性的TypeError。 - 令牌取值逻辑错误:代码直接将整个
req.cookies对象作为JWT令牌传给jwt.verify,没有从Cookie中取出对应字段存储的JWT字符串,本身传入的参数就不符合JWT校验的要求。 - 类型定义错误:中间件的请求入参被错误标注为
Authenticate类型,而非Express内置的Request类型,失去了类型校验的兜底能力。 - 逻辑嵌套冗余:无令牌的401拦截逻辑没有做提前返回,增加了不必要的嵌套层级。
修复方案
调整后的认证中间件代码
import { Request, Response, NextFunction } from "express"; import jwt from "jsonwebtoken"; const authenticate = (req: Request, res: Response, next: NextFunction) => { // 从Cookie的指定字段中读取JWT令牌 const token = req.cookies.jwt_token; if (!token) { // 无令牌场景提前返回,减少逻辑嵌套 return res.sendStatus(401); } jwt.verify(token, process.env.JWT_TOKEN_KEY, (error, payload) => { // 回调参数避开外层res的命名冲突,用payload指代解码的用户信息 if (error) { return res.sendStatus(403); } // 将解码出的用户信息挂载到请求对象上,供后续路由使用 (req as any).userInfo = { _id: payload._id, locale: payload.locale }; next(); }); }; export default authenticate;
对应测试代码调整
测试用例发起请求时,需要提前生成测试用JWT令牌,并将其设置到和中间件读取规则一致的Cookie字段中,而非随意传参:
// 提前调用jwt.sign生成测试令牌 const testToken = jwt.sign({_id: "567", locale: "en"}, process.env.JWT_TOKEN_KEY); describe("GET /user/:id", () => { it("return user information", () => { api .get("/user/123") .set("Cookie", `jwt_token=${testToken};locale=en`) .end(function (err, res) { chai.expect(res).to.have.status(200); }); }); });
内容的提问来源于stack exchange,提问作者HelloWorldEngineer
相关产品推荐
相关产品推荐

