使用Sinon对Vuex Action内的AuthService类做Mock实现单元测试
问题根因
你现有写法Stub的是AuthService的静态方法getToken,但业务代码中调用的是new AuthService()生成的实例的原型方法,两者不属于同一个挂载对象,因此Stub不会生效。
方案1:Stub原型方法(最简方案,无需修改业务代码)
直接修改测试中的Stub逻辑,针对类的原型方法做Stub,所有实例调用getToken都会命中模拟返回值:
- 把原有Stub代码替换为原型方法Stub
- 把
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
相关产品推荐
相关产品推荐

