如何使用Vitest正确模拟Vue 3中的Composable函数?
如何在Vitest中测试Vue 3 Composable的方法调用与参数传递
问题根源
你当前的测试写法无效,核心原因是:你创建的spyFetchHelpMate只是原fetchHelpMate函数的一个包装副本,和组件内部调用useHelpMateApi()返回的fetchHelpMate不是同一个引用。组件实际执行的还是原函数,你的 spy 根本不会被触发。
正确测试方案
需要mock整个useHelpMateApi Composable,让它返回带有 spy 的方法,这样组件调用时会直接使用这个 spy 函数,从而可以捕获调用行为和参数。
步骤1:Mock Composable模块
假设你的useHelpMateApi定义在@/composables/useHelpMateApi文件中,先在测试文件顶部mock该模块:
import { useHelpMateApi } from '@/composables/useHelpMateApi'; import { mount } from '@vue/test-utils'; import BotSettings from '@/components/BotSettings.vue'; import router from '@/router'; import pinia from '@/stores'; // Mock整个useHelpMateApi Composable vi.mock('@/composables/useHelpMateApi', () => ({ useHelpMateApi: vi.fn(() => ({ fetchHelpMate: vi.fn() })) }));
步骤2:编写测试用例
在测试用例中,先获取mock后的spy函数,设置路由参数,挂载组件后进行断言:
test('should fetch the HelpMate with the correct ID', async () => { // 从mock的Composable中取出spy函数 const mockFetchHelpMate = useHelpMateApi().fetchHelpMate; // 设置路由参数,确保组件能拿到正确的params.id await router.push('/bot-settings/123'); await router.isReady(); // 挂载组件 mount(BotSettings, { global: { plugins: [router, pinia] } }); // 断言调用次数与参数正确性 expect(mockFetchHelpMate).toHaveBeenCalledOnce(); expect(mockFetchHelpMate).toHaveBeenCalledWith('123'); });
额外说明
- 必须调用
router.push和router.isReady(),确保路由状态同步,组件能获取到正确的params.id - 如果你的
useHelpMateApi内部依赖其他Composable(如useRoute),可根据测试需求补充对应的mock逻辑 - 若组件内的API调用包含后续异步处理,可使用
await flushPromises()确保所有异步操作完成后再断言
内容的提问来源于stack exchange,提问作者Sensanaty
相关产品推荐
相关产品推荐

