如何在Vue3/Nuxt3 Composition API中用Vitest Mock i18n的t()函数?
解决Nuxt3/Vue3中Vitest Mock useI18n的
$setup.t is not a function错误 问题根源
你当前的测试代码同时混用了三种mock方式(vi.mock('vue-i18n')、mockNuxtImport('useI18n')、全局mocks),导致mock逻辑冲突。另外,Nuxt3项目中useI18n是从@nuxtjs/i18n包导出的,而非vue-i18n,这也是mock失效的核心原因之一。
正确解决方案
方案1:使用mockNuxtImport(Nuxt官方推荐)
这是最适配Nuxt3的mock方式,直接mock Nuxt的useI18n导入:
import { shallowMount } from '@vue/test-utils' import Overview from './[...slug].vue' import { mockNuxtImport } from '@nuxt/test-utils/runtime' import { vi } from 'vitest' // 正确mock Nuxt的useI18n mockNuxtImport('useI18n', () => { return vi.fn(() => ({ t: (key) => key, // 直接返回key作为翻译结果 locale: ref('en') })) }) describe('overview page', () => { let wrapper it('is a Vue instance', () => { wrapper = shallowMount(Overview, { global: { // 不需要额外的全局mock,mockNuxtImport已经处理了useI18n } }) expect(wrapper.vm).toBeTruthy() }) })
方案2:全局mock $t(适配模板直接调用的场景)
如果你想通过全局mock解决,需要注意:<script setup>中解构的t不会自动挂载到组件实例(vm)上,模板中直接使用t()时,需要确保全局有可用的$t,或者修改组件把t暴露给模板:
组件修改(可选)
在<script setup>中添加:
// 把t暴露给模板,这样模板可以直接用t defineExpose({ t })
测试代码修改
import { shallowMount } from '@vue/test-utils' import Overview from './[...slug].vue' import { vi } from 'vitest' describe('overview page', () => { let wrapper it('is a Vue instance', () => { wrapper = shallowMount(Overview, { global: { mocks: { $t: (key) => key // 全局mock $t,模板中可以使用$t() } } }) expect(wrapper.vm).toBeTruthy() }) })
注意:这种方式需要把组件模板中的
t('xxx')改成$t('xxx'),或者按上面的方式把t暴露给模板。
关键注意事项
- 不要同时混用多种mock方式,选择一种即可,避免冲突。
- Nuxt3的
useI18n来自@nuxtjs/i18n,不是vue-i18n,mock时要对应正确的包名。 <script setup>中的变量默认是私有的,模板中直接使用解构的t时,要么确保useI18n的mock正确注入,要么通过defineExpose暴露变量。
内容的提问来源于stack exchange,提问作者user66875
相关产品推荐
相关产品推荐

