如何在Node.js(Sails.js)单元测试中Mock JWT Access Token?
嘿,我刚好在Sails.js项目里用Mocha+Chai做过类似的JWT认证Mock,给你分享几个实用的方案,帮你搞定受保护端点的单元测试:
方案1:直接生成合法测试用JWT Token
如果你的测试重点是端点的业务逻辑,而非认证流程本身,直接生成一个有效的Token是最省心的方式。毕竟单元测试不需要真的走完整的登录流程,只要能通过认证校验就行。
步骤很简单:
- 找到你Sails项目里的JWT配置(通常在
config/custom.js或单独的config/jwt.js里),拿到签名密钥(比如process.env.JWT_SECRET或者sails.config.custom.jwtSecret)。 - 在测试文件里用
jsonwebtoken库生成测试Token:
const jwt = require('jsonwebtoken'); // 模拟一个测试用户的信息,和你业务里的用户结构保持一致 const testUser = { id: 1, email: 'test@example.com', role: 'user' }; // 生成有效期1小时的测试Token const validTestToken = jwt.sign(testUser, sails.config.custom.jwtSecret, { expiresIn: '1h' });
- 请求受保护端点时,把Token放到
Authorization请求头里:
it('should return protected user data', (done) => { chai.request(sails.hooks.http.app) .get('/api/user/profile') .set('Authorization', `Bearer ${validTestToken}`) .end((err, res) => { expect(res).to.have.status(200); expect(res.body.user.id).to.equal(testUser.id); done(); }); });
方案2:Mock Sails的认证政策(Policy)
如果你的受保护端点是通过Sails的政策来做JWT验证的(比如api/policies/isAuthenticated.js),直接Mock这个政策会更彻底,完全跳过Token校验环节,直接模拟用户已登录的状态。
首先需要安装sinon这个Mock工具:
npm install sinon --save-dev
然后在测试文件里做如下配置:
const sinon = require('sinon'); let authPolicyStub; // 所有测试开始前Mock政策 before((done) => { // 替换isAuthenticated政策的中间件 authPolicyStub = sinon.stub(sails.hooks.policies.middleware, 'isAuthenticated'); // 让政策直接通过验证,并给req挂载模拟的用户信息 authPolicyStub.callsFake((req, res, next) => { req.user = { id: 1, email: 'test@example.com' }; return next(); }); done(); }); // 所有测试结束后恢复原政策,避免影响其他测试 after((done) => { authPolicyStub.restore(); done(); }); // 现在请求受保护端点不需要带Token了 it('should access protected endpoint without real token', (done) => { chai.request(sails.hooks.http.app) .get('/api/admin/dashboard') .end((err, res) => { expect(res).to.have.status(200); done(); }); });
方案3:Mock JWT验证服务
如果你的认证逻辑封装在自定义服务里(比如api/services/JwtService.js),可以直接Mock这个服务的验证方法,让它直接返回模拟的用户信息。
还是用sinon来实现:
const sinon = require('sinon'); let jwtServiceStub; before((done) => { // Mock JwtService的verifyToken方法 jwtServiceStub = sinon.stub(sails.services.jwtservice, 'verifyToken'); // 不管传入什么Token,都返回模拟用户 jwtServiceStub.returns({ id: 1, email: 'test@example.com' }); done(); }); after((done) => { jwtServiceStub.restore(); done(); }); // 这时随便传个假Token就能通过验证 it('should accept fake token with mocked service', (done) => { chai.request(sails.hooks.http.app) .get('/api/orders') .set('Authorization', 'Bearer fake-token-123') .end((err, res) => { expect(res).to.have.status(200); done(); }); });
一些额外建议
- 单元测试的核心是隔离依赖:如果测试的是端点业务逻辑,优先用方案2或3跳过认证;如果要测试认证本身(比如Token过期、无效Token的错误处理),再用方案1生成对应状态的Token。
- 别忘了在测试前后启动/关闭Sails app:通常会在测试文件开头加
before((done) => sails.lift(done));和after((done) => sails.lower(done));,或者用sails-hook-test-helper简化这个流程。 - 每个Mock的函数/政策都要在测试结束后恢复,避免污染其他测试用例的环境。
内容的提问来源于stack exchange,提问作者Sayed Alesawy
相关产品推荐
相关产品推荐

