如何使用Jest测试Node.js身份验证中间件?
如何用Jest测试Node.js身份验证中间件并模拟请求头?
你的测试代码无法运行,核心问题是没有正确模拟req、res对象的方法,也没处理JWT验证和环境变量的依赖。下面是完整的解决方案,分场景覆盖你的中间件逻辑:
1. 基础准备:模拟req、res和next
首先要给req添加header方法,给res添加status、json、send这些Express响应方法,用Jest的jest.fn()创建模拟函数,方便后续断言调用情况。
2. Mock依赖:JWT和环境变量
因为我们不需要真实的JWT验证,所以用Jest mock掉jsonwebtoken的verify方法,同时设置测试用的process.env.TOKEN_SECRET。
完整测试代码
import verifyToken from '../middleware/verifyToken'; import jwt from 'jsonwebtoken'; // Mock jsonwebtoken模块 jest.mock('jsonwebtoken'); describe('verifyToken middleware', () => { // 测试前设置环境变量 beforeEach(() => { process.env.TOKEN_SECRET = 'test-secret'; }); // 场景1:请求头没有token,返回401 test('returns 401 when no token is provided', () => { // 模拟req:header方法返回undefined const req = { header: jest.fn().mockReturnValue(undefined) }; // 模拟res:status返回自身,支持链式调用 const res = { status: jest.fn().mockReturnThis(), json: jest.fn() }; const next = jest.fn(); verifyToken(req, res, next); expect(req.header).toHaveBeenCalledWith('x_auth-token'); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ message: 'Access denied' }); expect(next).not.toHaveBeenCalled(); }); // 场景2:token无效,返回400 test('returns 400 when invalid token is provided', () => { const mockToken = 'invalid-token'; const req = { header: jest.fn().mockReturnValue(mockToken) }; const res = { status: jest.fn().mockReturnThis(), send: jest.fn() }; const next = jest.fn(); // 让jwt.verify抛出错误,模拟无效token jwt.verify.mockImplementation(() => { throw new Error('Invalid token'); }); verifyToken(req, res, next); expect(jwt.verify).toHaveBeenCalledWith(mockToken, process.env.TOKEN_SECRET); expect(res.status).toHaveBeenCalledWith(400); expect(res.send).toHaveBeenCalledWith('Invalid Token'); expect(next).not.toHaveBeenCalled(); }); // 场景3:token有效,调用next并设置req.user test('sets req.user and calls next when valid token is provided', () => { const mockToken = 'valid-token'; const mockUser = { id: '123', username: 'test-user' }; const req = { header: jest.fn().mockReturnValue(mockToken) }; const res = { status: jest.fn().mockReturnThis(), json: jest.fn(), send: jest.fn() }; const next = jest.fn(); // 让jwt.verify返回模拟的用户信息 jwt.verify.mockReturnValue(mockUser); verifyToken(req, res, next); expect(jwt.verify).toHaveBeenCalledWith(mockToken, process.env.TOKEN_SECRET); expect(req.user).toEqual(mockUser); expect(next).toHaveBeenCalled(); expect(res.status).not.toHaveBeenCalled(); }); });
关键说明
- 模拟req.header:通过
jest.fn().mockReturnValue()控制返回的token值,覆盖不同场景。 - 链式调用模拟:res的
status方法用mockReturnThis(),保证res.status(401).json(...)的链式调用不会报错。 - JWT Mock:用
jest.mock('jsonwebtoken')接管整个模块,通过mockImplementation或mockReturnValue控制verify的行为,模拟成功/失败情况。 - 环境变量:在
beforeEach里设置测试用的TOKEN_SECRET,避免依赖真实环境变量。
内容的提问来源于stack exchange,提问作者McDavid
相关产品推荐
相关产品推荐

