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

如何为Pinia Store调用的Composable方法sendEvent添加Jest Spy?

正确测试Pinia Store调用Composable方法的方式

核心思路

useUtils是返回包含方法的对象的组合式函数,直接监听模块导出的useUtils函数没用,必须监听它返回对象上的sendEvent方法,或是直接mock整个组合式函数的返回值。


方法一:Mock整个组合式模块并追踪调用

假设你的文件结构:

  • @/composables/utils.js:
export function useUtils() {
  const sendEvent = (eventName, params) => {
    // 实际业务逻辑
  }
  return { sendEvent }
}
  • @/stores/ui.js:
import { defineStore } from 'pinia'
import { useUtils } from '@/composables/utils'

export const useUiStore = defineStore('ui', {
  actions: {
    setTab(tabName) {
      // 其他逻辑
      useUtils().sendEvent('tab_switched', { tab: tabName })
    }
  }
})

测试文件写法:

import { useUiStore } from '@/stores/ui'
import { createPinia, setActivePinia } from 'pinia'
import { useUtils } from '@/composables/utils'

// 提前mock整个组合式模块
jest.mock('@/composables/utils', () => ({
  useUtils: jest.fn(() => ({
    sendEvent: jest.fn() // 创建mock函数用于追踪调用
  }))
}))

describe('ui store', () => {
  let uiStore
  let mockSendEvent

  beforeEach(() => {
    // 初始化Pinia环境
    setActivePinia(createPinia())
    uiStore = useUiStore()
    // 取出mock的sendEvent方法
    mockSendEvent = useUtils().sendEvent
  })

  it('calls sendEvent when setTab is invoked', () => {
    uiStore.setTab('home')
    // 验证调用次数与参数
    expect(mockSendEvent).toHaveBeenCalledTimes(1)
    expect(mockSendEvent).toHaveBeenCalledWith('tab_switched', { tab: 'home' })
  })
})

方法二:用jest.spyOn动态替换目标方法

如果不想完全mock整个模块,仅监听sendEvent:

import { useUiStore } from '@/stores/ui'
import { createPinia, setActivePinia } from 'pinia'
import * as utilsComposable from '@/composables/utils'

describe('ui store', () => {
  let uiStore
  let mockSendEvent

  beforeEach(() => {
    setActivePinia(createPinia())
    // 获取原组合式函数的返回对象,监听其sendEvent方法
    const originalUtils = utilsComposable.useUtils()
    mockSendEvent = jest.spyOn(originalUtils, 'sendEvent').mockImplementation(() => {})
    // 替换模块导出的useUtils,让它返回被监听的对象
    jest.spyOn(utilsComposable, 'useUtils').mockReturnValue(originalUtils)
    
    uiStore = useUiStore()
  })

  afterEach(() => {
    // 清除所有mock,避免影响其他测试用例
    jest.restoreAllMocks()
  })

  it('triggers sendEvent on setTab', () => {
    uiStore.setTab('profile')
    expect(mockSendEvent).toHaveBeenCalledTimes(1)
  })
})

常见失败原因

  1. 监听对象错误:直接监听模块导出的useUtils函数,而非它返回对象里的sendEvent方法,自然追踪不到调用。
  2. Pinia未初始化:测试前未执行setActivePinia(createPinia()),导致Store实例创建异常,方法未正确执行。
  3. mock时机滞后:在导入Store之后才mock组合式模块,Store已加载原模块的方法,mock未生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:55:24