如何在Vitest中模拟__()国际化函数?
如何模拟国际化函数
__()以解决Vitest测试报错问题? 问题描述
使用Laravel+Vue+Inertiajs技术栈,在通过Vitest测试组件时出现报错:TypeError: _ctx.__ is not a function
已通过Lingua库将Laravel语言文件转换为JS,使__()翻译函数在全局可用(已在app.js中引入),当前不需要测试该函数的翻译准确性,想确认模拟__()是否为正确解决方案。
示例组件代码
<script setup> import Checkbox from '@/Components/Checkbox.vue'; import InputError from '@/Components/InputError.vue'; import InputLabel from '@/Components/InputLabel.vue'; import PrimaryButton from '@/Components/PrimaryButton.vue'; import { useForm, usePage } from '@inertiajs/vue3'; const user = usePage().props.auth.user; const form = useForm({ inboxable: user.inboxable ?? true, }); const saveForm = (() => { form.patch(route('privacy.update'), { preserveScroll: true, }); }); </script> <template> <section> <header> <h2 class="text-lg font-medium text-gray-900">{{__('user.privacyTitle')}}</h2> <p class="mt-1 text-sm text-gray-600"> {{__('user.privacyDescription')}} </p> </header> <div></div> <form @submit.prevent="saveForm" class="mt-6 space-y-6"> <div> <InputLabel for="inboxable" :value="__('user.privacyInboxable')" /> <Checkbox id="inboxable" v-model="form.inboxable" :checked="form.inboxable" /> <InputError class="mt-2" :message="form.errors.inboxable" /> </div> <div class="flex items-center gap-4"> <PrimaryButton :disabled="form.processing">{{__('user.privacySave')}}</PrimaryButton> <Transition enter-from-class="opacity-0" leave-to-class="opacity-0" class="__ition ease-in-out"> <p v-if="form.recentlySuccessful" class="text-sm text-gray-600">{{__('user.profileConfirmed')}}</p> </Transition> </div> </form> </section> </template>
vite.config配置
import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import vue from '@vitejs/plugin-vue'; import path from 'path'; import { run } from 'vite-plugin-run' import basicSsl from '@vitejs/plugin-basic-ssl' export default defineConfig({ esbuild: { jsxFactory: 'h', jsxFragment: 'Fragment' }, plugins: [ basicSsl(), laravel({ input: 'resources/js/app.js', refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), run({ name: "generate translations", run: ['php', 'artisan', 'lingua:generate'], pattern: ['resources/lang/**', 'lang/**'], }), ], server: { hmr: { host: "192.168.10.1", https: true, }, host: "0.0.0.0", https: true, }, resolve: { alias: { 'lingua-js': path.resolve(__dirname, 'vendor/cyberwolfstudio/lingua/dist/index.js') }, }, test: { globals: true, environment: "jsdom", }, });
解决方案
模拟__()函数是完全可行的方案,以下是三种实现方式:
- 单个测试文件内全局模拟
在测试文件顶部添加全局函数模拟:
import { vi } from 'vitest'; // 直接返回传入的翻译键,满足测试组件渲染需求 vi.stubGlobal('__', (key) => key);
- 全局测试前置配置
修改vite.config.js的test字段,指定前置配置文件:
test: { globals: true, environment: "jsdom", setupFiles: ['./tests/setup.js'], },
创建tests/setup.js文件并写入:
import { vi } from 'vitest'; vi.stubGlobal('__', (key) => key);
- 组件挂载时注入
在挂载组件时通过全局配置注入函数:
import { mount } from '@vue/test-utils'; import PrivacyComponent from './PrivacyComponent.vue'; test('组件渲染正常', () => { const wrapper = mount(PrivacyComponent, { global: { config: { globalProperties: { __: (key) => key, }, }, }, }); // 编写断言逻辑 });
以上方式均可解决测试时__()函数未定义的报错,可根据测试结构选择合适的方案。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

