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

升级jsonwebtoken至9.0.0后,Sinon Stub decode函数报错TypeError

解决方案:jsonwebtoken 9.0.0中无法Stub decode函数的问题

问题原因

jsonwebtoken 9.x版本重构了导出逻辑,decode函数通过Object.defineProperty定义时设置了configurable: false,这意味着该属性无法被重新定义或删除,而sinon的stub本质是覆盖原有属性,因此直接操作会抛出TypeError: Cannot redefine property: decode错误。verify函数未采用相同的定义方式,所以可以正常Stub。

可行解决方案

方案1:修改属性可配置性后再Stub

在Stub前先修改decode属性的可配置性,让sinon能够覆盖它:

const jwt = require('jsonwebtoken');
const sinon = require('sinon');

beforeEach(() => {
  // 获取decode属性的描述符
  const decodeDesc = Object.getOwnPropertyDescriptor(jwt, 'decode');
  // 修改为可配置
  decodeDesc.configurable = true;
  Object.defineProperty(jwt, 'decode', decodeDesc);
  
  // 现在可以正常Stub
  sinon.stub(jwt, 'decode').returns({ userId: 'test-user-id' });
});

afterEach(() => {
  // 恢复原始属性(可选,避免影响其他测试)
  sinon.restore();
});

方案2:使用proxyquire替换整个jsonwebtoken模块

通过proxyquire在测试中注入一个模拟的jsonwebtoken模块,完全规避原有模块的属性限制:

const sinon = require('sinon');
const proxyquire = require('proxyquire');

describe('你的测试套件', () => {
  let targetModule;
  let jwtMock;

  beforeEach(() => {
    // 创建包含可Stub方法的模拟对象
    jwtMock = {
      decode: sinon.stub().returns({ userId: 'test-user-id' }),
      verify: sinon.stub().returns({ userId: 'test-user-id' })
    };
    // 加载目标模块并替换jsonwebtoken为模拟对象
    targetModule = proxyquire('../路径/到/你的/模块', {
      'jsonwebtoken': jwtMock
    });
  });

  it('测试用例示例', () => {
    // 执行测试逻辑
    targetModule.someFunctionUsingJwt();
    // 断言decode被调用
    sinon.assert.calledOnce(jwtMock.decode);
  });
});

方案3:直接模拟decode的实现逻辑(临时替代)

如果上述方案无法使用,也可以直接在测试代码中手动模拟decode的行为,比如在目标模块中添加一个可替换的依赖入口:

// 你的业务模块中,将jwt依赖改为可注入
let jwt = require('jsonwebtoken');

// 暴露用于测试的替换方法
if (process.env.NODE_ENV === 'test') {
  module.exports.setJwt = (mockJwt) => {
    jwt = mockJwt;
  };
}

// 业务逻辑中使用jwt.decode
function yourFunction(token) {
  return jwt.decode(token);
}

然后在测试中替换:

const yourModule = require('../path/to/your/module');
const sinon = require('sinon');

beforeEach(() => {
  const mockJwt = {
    decode: sinon.stub().returns({ userId: 'test-id' }),
    verify: sinon.stub()
  };
  yourModule.setJwt(mockJwt);
});

内容的提问来源于stack exchange,提问作者Rasmus Puls

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:25:22