如何mock jsonwebtoken和jwks-rsa以测试Lambda自定义授权器
Lambda自定义授权器测试方案
核心思路
完全隔离外部依赖,不需要发起任何HTTP请求,通过本地mock依赖和自签密钥完成全场景测试。
具体实现步骤
- 步骤1:Mock外部依赖库
用你常用的测试框架(比如Jest、Mocha+Sinon)直接mockjwks-rsa和jsonwebtoken两个核心依赖,跳过真实的JWKS接口请求:- mock
jwks-rsa返回的客户端实例的getSigningKey方法,无需调用远端接口,直接根据测试场景返回预设的公钥或者错误。 - 按需mock
jsonwebtoken的decode和verify方法,模拟令牌解析、校验成功/失败的各种情况。
- mock
- 步骤2:本地生成测试用密钥对
你可以本地生成一对RSA密钥对,测试时用私钥签发测试用JWT,mock返回的公钥和私钥对应,就能完整走通签名校验逻辑,完全不需要依赖Auth0服务。 - 步骤3:覆盖全量测试场景
你需要覆盖这些核心场景确保授权逻辑正确:- 携带有效JWT时返回Allow策略,且principalId、context字段符合预期
- 缺失Authorization头时返回Deny策略
- 令牌格式错误、过期、签名不匹配时返回Deny策略
- 令牌的audience、issuer和预设值不匹配时返回Deny策略
- 获取签名密钥失败时返回Deny策略
示例测试代码(基于Jest)
const { auth } = require('./authorizer'); const jwt = require('jsonwebtoken'); const jwks = require('jwks-rsa'); // 本地生成的测试用RSA密钥对 const TEST_PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY----- 你的测试私钥内容 -----END RSA PRIVATE KEY-----`; const TEST_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- 你的测试公钥内容 -----END PUBLIC KEY-----`; // Mock jwks-rsa jest.mock('jwks-rsa'); const mockGetSigningKey = jest.fn(); jwks.mockReturnValue({ getSigningKey: mockGetSigningKey }); // 模拟环境变量 process.env.AUDIENCE = 'test-audience'; process.env.TOKEN_ISSUER = 'test-issuer'; describe('Lambda Authorizer测试', () => { beforeEach(() => { jest.clearAllMocks(); }); test('有效令牌返回Allow策略', async () => { // 生成有效测试令牌 const token = jwt.sign( { sub: 'test-user-id', scope: 'read write' }, TEST_PRIVATE_KEY, { algorithm: 'RS256', keyid: 'test-kid', audience: 'test-audience', issuer: 'test-issuer', expiresIn: '1h' } ); // mock返回公钥 mockGetSigningKey.mockImplementation((kid, callback) => { callback(null, { publicKey: TEST_PUBLIC_KEY }); }); const event = { authorizationToken: `Bearer ${token}` }; const result = await auth(event); expect(result.principalId).toBe('test-user-id'); expect(result.policyDocument.Statement[0].Effect).toBe('Allow'); expect(result.context.scope).toBe('read write'); }); test('无效令牌返回Deny策略', async () => { const event = { authorizationToken: 'Bearer invalid-token' }; const result = await auth(event); expect(result.policyDocument.Statement[0].Effect).toBe('Deny'); }); });
优化建议
你可以稍微调整现有代码,把jwks客户端的创建改成可注入的形式,比如把client作为参数传入verifyToken函数,测试时可以直接传入自定义的测试客户端,不需要mock模块,代码可测试性会更高。
内容的提问来源于stack exchange,提问作者Jatin Mehrotra
相关产品推荐
相关产品推荐

