如何为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) }) })
常见失败原因
- 监听对象错误:直接监听模块导出的
useUtils函数,而非它返回对象里的sendEvent方法,自然追踪不到调用。 - Pinia未初始化:测试前未执行
setActivePinia(createPinia()),导致Store实例创建异常,方法未正确执行。 - mock时机滞后:在导入Store之后才mock组合式模块,Store已加载原模块的方法,mock未生效。
内容的提问来源于stack exchange,提问作者Cornwell
相关产品推荐
相关产品推荐

