Vue3从Vuex转Pinia后单元测试失败,无法创建自定义模拟Store
解决Pinia在Vue3单元测试中自定义模拟Store的问题
下面提供两种可行方案,帮你在Jest+vue/test-utils环境中创建可被组件使用的自定义测试Pinia Store:
方案1:创建测试专用Pinia实例并注入自定义Store
这种方法适合直接在测试文件中定义临时测试Store,无需修改原代码:
- 初始化Pinia测试实例并设置为活跃状态
- 定义自定义测试Store
- 挂载组件时将Pinia实例作为插件传入
import { createPinia, setActivePinia, defineStore } from 'pinia' import { mount } from '@vue/test-utils' import PasswordResetPage from '@/views/PasswordReset.vue' let pinia let authTestStore beforeEach(() => { // 创建Pinia实例并激活,避免"找不到活跃Pinia实例"错误 pinia = createPinia() setActivePinia(pinia) // 定义自定义测试Store,模拟密码重置成功逻辑 const useCustomAuthStore = defineStore('AuthenticationStore', { state: () => ({ passwordResetSuccess: false }), actions: { forgotPasswordResetPassword() { // 绕过后端,直接更新状态 this.passwordResetSuccess = true } } }) // 实例化测试Store authTestStore = useCustomAuthStore() }) test('点击重置按钮后状态更新为成功', async () => { const wrapper = mount(PasswordResetPage, { global: { plugins: [pinia] } }) // 触发重置按钮点击事件 await wrapper.find('#reset-password-btn').trigger('click') // 验证状态是否正确更新 expect(authTestStore.passwordResetSuccess).toBe(true) })
方案2:Jest Mock原Store模块
如果你的项目中将useAuthenticationStore定义在单独的store文件中(比如src/stores/authentication.js),可以直接Mock整个模块:
import { createPinia, setActivePinia, defineStore } from 'pinia' import { mount } from '@vue/test-utils' import PasswordResetPage from '@/views/PasswordReset.vue' // Mock原Store模块,替换为自定义测试Store jest.mock('@/stores/authentication', () => { const useMockAuthStore = defineStore('AuthenticationStore', { state: () => ({ passwordResetSuccess: false }), actions: { forgotPasswordResetPassword() { this.passwordResetSuccess = true } } }) return { useAuthenticationStore: useMockAuthStore } }) beforeEach(() => { // 激活Pinia实例,确保Mock的Store能正常初始化 const pinia = createPinia() setActivePinia(pinia) }) test('触发重置操作后状态标记为成功', async () => { const wrapper = mount(PasswordResetPage, { global: { plugins: [createPinia()] } }) // 获取Mock的Store实例 const { useAuthenticationStore } = require('@/stores/authentication') const authStore = useAuthenticationStore() // 触发按钮点击 await wrapper.find('.reset-btn').trigger('click') // 验证状态更新 expect(authStore.passwordResetSuccess).toBe(true) })
关键注意事项
- 必须在调用
defineStore和useStore之前执行setActivePinia(pinia),否则会抛出"找不到活跃Pinia实例"的错误 - 如果action是异步函数,测试时要添加
await等待执行完成 - 若组件中使用
storeToRefs获取状态,测试时可直接通过Store实例访问状态,无需额外处理响应式问题
内容的提问来源于stack exchange,提问作者DaveCode
相关产品推荐
相关产品推荐

