Vitest测试Pinia状态未更新求助:API调用后projects数组为空
问题:Pinia Store中getAllProjects方法测试时状态未更新
开发Vue.js应用时,使用Pinia做状态管理、Vitest做单元测试。Pinia store里的getAllProjects方法通过API获取项目数据并更新store状态,但测试时模拟API调用后,store的projects数组未按预期更新,测试失败提示:
Expected: 3, Received: 0
原因分析
- 未模拟axios请求:当前测试代码没有对axios的
get请求做模拟,测试时会发送真实API请求,而真实请求无返回数据,导致projects数组保持为空。 - state缺失loading字段:store的state未定义
loading属性,但在getAllProjects中直接赋值this.loading = true,会导致状态异常,可能影响后续逻辑执行。 - async/await与.then/.catch混用:在async函数里同时使用两种异步写法,逻辑嵌套混乱,可能导致状态更新时机出现问题。
解决方案
步骤1:修复Pinia Store代码
在state中添加loading字段,同时重构getAllProjects方法,统一使用async/await写法:
import { defineStore } from 'pinia'; import axios from '@/utils/axios'; import Swal from 'sweetalert2'; export const useProjectStore = defineStore('project', { state: () => ({ projects: [], loading: false // 新增loading字段 }), actions: { async getAllProjects() { this.loading = true; try { const response = await axios.get('projects', { timeout: 15000 }); this.projects = response.data; } catch (error) { console.error(error); } finally { this.loading = false; // 用finally确保loading一定会被重置 } }, }, persist: true, });
步骤2:修改Vitest测试代码,模拟axios请求
使用Vitest的vi.mock模拟axios模块,让get方法返回预设的模拟数据:
import { describe, test, expect, beforeEach, vi } from 'vitest' import { setActivePinia, createPinia } from 'pinia' import { useProjectStore } from '@/stores/project' import axios from '@/utils/axios'; // 导入路径需和store中一致 // 模拟axios模块 vi.mock('@/utils/axios', () => ({ default: { get: vi.fn() } })) describe('Projects', () => { let store = null beforeEach(() => { setActivePinia(createPinia()) store = useProjectStore() // 每次测试前重置mock,避免用例间干扰 axios.get.mockReset() }) test('初始状态下projects为空数组', () => { expect(store.projects).toEqual([]) }) test('调用getAllProjects后projects被填充为3条数据', async () => { // 模拟axios.get返回3条项目数据 axios.get.mockResolvedValue({ data: [ { id: 1, name: '项目1' }, { id: 2, name: '项目2' }, { id: 3, name: '项目3' } ] }) await store.getAllProjects() expect(axios.get).toHaveBeenCalledWith('projects', { timeout: 15000 }) expect(store.projects).toHaveLength(3) }) })
关键说明
- mock路径匹配:模拟axios时,导入路径必须和store中
@/utils/axios完全一致,否则mock不会生效。 - 重置mock:在
beforeEach中调用mockReset(),避免不同测试用例的mock状态互相干扰。 - finally块重置loading:使用
finally确保无论请求成功或失败,loading状态都会被重置,避免状态不一致。
内容的提问来源于stack exchange,提问作者Dogukan Kalemli
相关产品推荐
相关产品推荐

