Vue项目用Sinon模拟$http编写API单元测试遇阻求助
解决Vue.js API封装方法的Sinon Mock测试问题
首先假设你的apiList.ts是如下常见结构(基于Vue原型的$http封装):
import Vue from 'vue'; export const getUsers = () => { return Vue.prototype.$http.get('/api/users'); }; export const addUser = (user: any) => { return Vue.prototype.$http.post('/api/users', user); }; export const updateUser = (id: number, user: any) => { return Vue.prototype.$http.put(`/api/users/${id}`, user); };
以下是能正确Mock$http并执行所有日志的测试用例(以Jest+Sinon为例,Mocha+Chai可直接替换断言逻辑):
import Vue from 'vue'; import sinon from 'sinon'; import { getUsers, addUser, updateUser } from './apiList'; describe('API List 单元测试', () => { let httpGetStub: sinon.SinonStub; let httpPostStub: sinon.SinonStub; let httpPutStub: sinon.SinonStub; // 每个测试前初始化Mock beforeEach(() => { // 创建带Stub的Mock $http对象 const mockHttp = { get: sinon.stub().resolves({ data: [{ id: 1, name: 'test' }] }), post: sinon.stub().resolves({ data: { id: 2, name: 'new' } }), put: sinon.stub().resolves({ data: { id: 1, name: 'updated' } }) }; // 替换Vue原型上的$http Vue.prototype.$http = mockHttp; // 保存Stub引用方便后续断言 httpGetStub = mockHttp.get; httpPostStub = mockHttp.post; httpPutStub = mockHttp.put; }); // 每个测试后恢复原始状态,避免污染其他测试 afterEach(() => { delete Vue.prototype.$http; sinon.restore(); }); test('getUsers 应正确调用$http.get', async () => { console.log('step1'); const result = await getUsers(); console.log('step2'); // 断言请求方法和URL正确 expect(httpGetStub.calledOnceWith('/api/users')).toBe(true); console.log('step3'); expect(result.data.length).toBe(1); console.log('step4'); }); test('addUser 应正确调用$http.post', async () => { console.log('step5'); const testUser = { name: 'new user' }; const result = await addUser(testUser); console.log('step6'); expect(httpPostStub.calledOnceWith('/api/users', testUser)).toBe(true); expect(result.data.name).toBe('new'); console.log('step7'); }); test('updateUser 应正确调用$http.put', async () => { const testUserId = 1; const updatedData = { name: 'updated user' }; await updateUser(testUserId, updatedData); expect(httpPutStub.calledOnceWith(`/api/users/${testUserId}`, updatedData)).toBe(true); }); });
关键问题修复点
- 必须用
await处理异步请求:你的日志step3、5不执行,很大概率是没await异步的API方法,导致测试直接结束,后续代码无法执行。 - Mock对象要替换到正确的位置:确保替换的是
Vue.prototype.$http而非Vue.$http,这是原型挂载的核心点。 - Stub需处理异步Promise:用
resolves()模拟请求成功的响应,让await能正确拿到结果,避免Promise一直pending。 - 测试前后的状态隔离:用
beforeEach和afterEach分别初始化Mock和恢复原始Vue原型,防止测试用例间相互污染。
内容的提问来源于stack exchange,提问作者RSKMR
相关产品推荐
相关产品推荐

