如何在Vitest中Mock $csrfFetch?(基于nuxt-csurf模块)
如何在Vitest中Mock Nuxt的useCsrfFetch和$csrfFetch方法
我在项目中使用nuxt-csurf模块,因此必须通过useCsrfFetch和$csrfFetch方法发起请求。手动测试时功能正常,但在Vitest中需要对这两个函数进行Mock,尝试了两种方案都失败了:
方案一直接MockuseNuxtApp引发大量Nuxt内部错误:
vi.mock('../../node_modules/nuxt/dist/app/nuxt', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useNuxtApp: vi.fn(() => { const nuxtApp = actual.useNuxtApp(); return { ...nuxtApp, $csrfFetch: vi.fn(async (...args) => { console.log('$csrfFetch called with:', args); return { data: 'mocked response' }; }), }; }), }; });
方案二尝试SpyOn$csrfFetch时抛出错误:
const nuxtApp = useNuxtApp(); const spy = vi.spyOn(nuxtApp, '$csrfFetch').mockImplementation(() => Promise.resolve({ state: 'response data' }), );
TypeError: Cannot redefine property: $csrfFetch
正确的Mock方案
1. 直接Mock useCsrfFetch
如果代码中直接调用useCsrfFetch,可以直接Mock这个函数:
// 在测试文件顶部执行 vi.mock('#app', () => ({ useCsrfFetch: vi.fn(async (...args) => { console.log('useCsrfFetch called with:', args); return Promise.resolve({ data: 'mocked response' }); }) }));
2. Mock NuxtApp中的$csrfFetch
如果代码通过useNuxtApp()获取$csrfFetch,直接MockuseNuxtApp返回包含模拟方法的对象即可,无需调用原函数:
vi.mock('#app', () => ({ useNuxtApp: vi.fn(() => ({ $csrfFetch: vi.fn(async (...args) => { console.log('$csrfFetch called with:', args); return Promise.resolve({ state: 'response data' }); }) })) }));
3. 组件测试中通过Provide注入Mock
测试Vue组件时,也可以通过provide直接注入Mock的$csrfFetch:
import { mount } from '@vue/test-utils'; import YourComponent from './YourComponent.vue'; test('组件调用$csrfFetch时触发Mock', async () => { const mockCsrfFetch = vi.fn(() => Promise.resolve({ data: 'test data' })); const wrapper = mount(YourComponent, { global: { provide: { $csrfFetch: mockCsrfFetch } } }); // 触发组件中调用$csrfFetch的操作 await wrapper.find('.submit-btn').trigger('click'); expect(mockCsrfFetch).toHaveBeenCalled(); });
原方案失败原因说明
- 方案一:直接Mock
nuxt/dist/app/nuxt中的useNuxtApp并调用原函数,会破坏Nuxt内部的上下文依赖链,测试环境无法提供原函数所需的运行上下文,因此引发大量内部错误。 - 方案二:
$csrfFetch是Nuxt注入的不可配置属性,vi.spyOn无法修改这类属性,因此抛出Cannot redefine property错误。
内容的提问来源于stack exchange,提问作者L1nux
相关产品推荐
相关产品推荐

