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

使用Sinon对Vuex Action内的AuthService类做Mock实现单元测试

问题根因

你现有写法Stub的是AuthService的静态方法getToken,但业务代码中调用的是new AuthService()生成的实例的原型方法,两者不属于同一个挂载对象,因此Stub不会生效。

方案1:Stub原型方法(最简方案,无需修改业务代码)

直接修改测试中的Stub逻辑,针对类的原型方法做Stub,所有实例调用getToken都会命中模拟返回值:

  1. 把原有Stub代码替换为原型方法Stub
  2. 把afterEach中的sinon.reset()改为sinon.restore(),避免Stub在测试用例间互相污染(reset仅清空调用历史,restore会恢复原生方法实现)

修改后对应测试用例代码如下:

it.only('returns a token from the AuthService & sets it in the store', async () => {
  const commit = sinon.spy();
  const mockResponse = {
    token: 'bobbins'
  };
  // 关键修改:stub原型上的getToken方法
  sinon.stub(AuthService.prototype, 'getToken').resolves(mockResponse);

  const requestParams = { commit, rootState: state };
  await actions[SIGN_IN](requestParams);

  expect(commit.calledOnce).toEqual(true);
  expect(commit.args[0][0]).toEqual('SET_AUTH_TOKEN');
  expect(commit.args[0][1]).toEqual(mockResponse);
});

对应的afterEach修改:

afterEach(() => {
  sinon.restore();
});

方案2:完全Mock整个AuthService类(适用需要屏蔽构造函数逻辑的场景)

如果你的测试需要避免AuthService构造函数中实例化PublicClientApplication的逻辑执行,可以直接替换整个类的导入:
如果是Jest环境,直接在测试文件顶部添加模块Mock逻辑:

// 放在导入AuthService的代码之前
jest.mock('../../../../../src/authService', () => {
  const mockGetToken = jest.fn().mockResolvedValue({ token: 'bobbins' });
  return jest.fn(() => ({
    getToken: mockGetToken
  }));
});

如果用Sinon配合构建工具的mock能力(比如Vite的vi.mock、Webpack的inject-loader),也可以实现完全替换类的效果,不会执行原生的构造函数逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:39:00