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

如何在单元测试中初始化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:10:03