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

Pinia异步Action单元测试问题:router.push未触发

问题解决:异步Pinia Action后router.push的单元测试断言失败

问题原因

你的测试代码没有等待异步操作完成就执行了断言:resolve是异步函数,点击按钮触发后,await store.resolveId()会将后续代码(包括router.push)推入微任务队列,而测试里同步执行expect时,微任务还没执行,所以断言失败。另外createTestingPinia默认会stub所有Pinia Actions,需要确保resolveId正确返回且store.apiUrl被设置为真值,才会走到router.push的逻辑分支。

解决方案

步骤1:让测试等待异步流程完成

将测试函数标记为async,通过await等待点击事件触发的异步操作执行完毕,或者用flushPromises刷新微任务队列。

步骤2:Mock Pinia Action并设置必要的store状态

手动mockstore.resolveId让它返回resolved状态的Promise,同时设置store.apiUrl为真值,保证代码能进入router.push的分支。

修改后的测试代码

import { flushPromises } from '@vue/test-utils'
import { useStore } from '@/stores/your-store' // 替换为你的实际store路径
import { useRouter } from 'vue-router'

it('should redirect to root', async () => {
    const wrapper = mount(SelectTenant, {
        global: {
            plugins: [createTestingPinia()]
        }
    })

    // 获取store实例并配置
    const store = useStore()
    store.resolveId = vi.fn().mockResolvedValue() // mock异步Action返回成功
    store.apiUrl = 'https://example.com/api' // 设置apiUrl为真值

    // Mock router的push方法
    const router = useRouter()
    vi.spyOn(router, 'push')

    // 触发点击并等待异步流程完成
    await wrapper.find('#resolveButton').trigger('click')
    // 也可以用flushPromises刷新所有微任务
    // await flushPromises()

    expect(router.push).toHaveBeenCalledWith('/')
})

关键注意点

  • 测试函数必须声明为async,通过await等待异步操作结束
  • 必须确保store.apiUrl为真值,否则不会执行router.push
  • 用vi.spyOn或直接mock router的push方法,才能正确捕获调用行为
  • 手动mock Pinia Action的返回值,保证await后的代码能正常执行

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:20:02