如何在单元测试中初始化Pinia Store的私有状态myProp
Pinia私有状态单元测试预置数据解决方案
问题场景
给定如下Pinia Store代码:
export const useMyStore = defineStore("MyStore", () => { // 私有状态 const myProp = ref<string[]>([]) // 填充状态的异步方法 const fetch = async ()=>{ myProp.value = await someHttpRequest() } // 操作私有状态的私有方法 const myPrivateMethod = (): void => { myProp.value.sort() // 示例排序逻辑 } // 导出的计算属性,返回私有状态的副本 const getMyProp = computed(()=>{ return [...myProp.value] }) // 公开方法,调用私有方法 const publicMethod = () => { myPrivateMethod() } return { fetch, getMyProp, publicMethod } })
需为私有状态myProp预置测试数据,调用publicMethod后验证myPrivateMethod的排序功能,但尝试Pinia文档中的initialState和自定义插件方法后,myProp始终为空列表。
核心原因
myProp是Store内部未暴露的私有状态,而initialState仅能初始化Store返回的公开状态,因此无法直接作用于私有变量。
可行解决方案
方案一:通过测试工具直接访问私有状态(Vitest/Jest)
利用Pinia的内部结构,在测试中获取Store setup函数的内部变量,直接修改私有状态的值:
import { useMyStore } from '@/stores/myStore' import { createTestingPinia } from '@pinia/testing' import { vi } from 'vitest' test('publicMethod 正确触发排序逻辑', () => { const pinia = createTestingPinia() const store = useMyStore(pinia) // 执行Store的setup函数,获取内部私有变量myProp const setupResult = useMyStore._def.setup({ pinia }) const myProp = setupResult.myProp || (setupResult as any).myProp // 预置测试数据 myProp.value = ['banana', 'apple', 'cherry'] // 调用公开方法 store.publicMethod() // 验证排序结果 expect(store.getMyProp).toEqual(['apple', 'banana', 'cherry']) })
方案二:为测试环境添加私有状态设置入口(优雅长期方案)
在Store中添加仅在测试环境生效的方法,用于设置私有状态,不影响生产代码:
// Store文件中修改返回逻辑 export const useMyStore = defineStore("MyStore", () => { const myProp = ref<string[]>([]) // ... 原有方法保持不变 // 仅在测试环境暴露的私有状态设置方法 const testSetMyProp = (value: string[]) => { myProp.value = value } // 根据环境决定返回内容 if (import.meta.env.MODE === 'test') { return { fetch, getMyProp, publicMethod, testSetMyProp } } return { fetch, getMyProp, publicMethod } })
测试代码:
import { useMyStore } from '@/stores/myStore' import { createTestingPinia } from '@pinia/testing' test('publicMethod 正确触发排序逻辑', () => { const pinia = createTestingPinia() // 类型断言,允许访问测试专用方法 const store = useMyStore(pinia) as ReturnType<typeof useMyStore> & { testSetMyProp: (value: string[]) => void } // 预置测试数据 store.testSetMyProp(['banana', 'apple', 'cherry']) // 调用公开方法 store.publicMethod() // 验证排序结果 expect(store.getMyProp).toEqual(['apple', 'banana', 'cherry']) })
方案三:Mock异步请求,通过fetch方法预置数据
如果无需单独测试私有状态的初始化,可MocksomeHttpRequest,调用fetch方法间接设置私有状态:
import { useMyStore } from '@/stores/myStore' import { createTestingPinia } from '@pinia/testing' import { vi } from 'vitest' import { someHttpRequest } from '@/api' // Mock异步请求,返回测试数据 vi.mock('@/api', () => ({ someHttpRequest: vi.fn().mockResolvedValue(['banana', 'apple', 'cherry']) })) test('publicMethod 正确触发排序逻辑', async () => { const pinia = createTestingPinia() const store = useMyStore(pinia) // 调用fetch方法,通过Mock的请求设置私有状态 await store.fetch() // 调用公开方法 store.publicMethod() // 验证排序结果 expect(store.getMyProp).toEqual(['apple', 'banana', 'cherry']) })
内容的提问来源于stack exchange,提问作者Aref Takiden
相关产品推荐
相关产品推荐

