我已经开始用 Vitest 替换 Jest,用于我的 Vue 3 应用程序中的单元测试库。
我正在尝试为使用 vue-i18n 库翻译其中文本的组件编写单元测试,但是当我尝试将此组件安装到我的测试文件中时,它失败并显示错误:
ReferenceError: t 未定义
在使用 vitest 库编写测试时,从
t
存根/模拟 import { useI18n } from 'vue-i18n'
的正确方法是什么?
注意,因为从 Vue2 升级到 Vue3,这不起作用:
const wrapper = shallowMount(MyComponent, {
global: {
mocks: {
$t: () => {}
}
}
})
这里是一些值得注意的软件包版本的列表:
"vue": "^3.2.31",
"vue-i18n": "^9.2.0-beta.14",
"vite": "^2.9.0",
"vitest": "^0.10.2"
谢谢!
import { createI18n } from 'vue-i18n';
describe('xxx', () => {
it('yyy', () => {
const i18n = createI18n({
messages: {
gb: {},
nl: {},
...
}
});
const wrapper = mount(YourComponent, {
global: {
plugins: [i18n]
}
});
}
})
我想你想在全球范围内模拟这个,不需要在每个测试套件中放置相同的代码。
// vitest.config.ts
import { mergeConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import viteConfig from './vite.config';
export default defineConfig(
mergeConfig(viteConfig, { // extending app vite config
test: {
setupFiles: ['tests/unit.setup.ts'],
environment: 'jsdom',
}
})
);
// tests/unit.setup.ts
import { config } from "@vue/test-utils"
config.global.mocks = {
$t: tKey => tKey; // just return translation key
};
Panos Vakalopoulos 的回答对我有用。
并且代码可以在全球范围内运行。
见https://test-utils.vuejs.org/migration/#no-more-createlocalvue
// vite.config.ts
export default defineConfig(
// add config for test
test: {
environment: 'jsdom',
setupFiles: 'vitest.setup.ts',
}
);
// vitest.setup.ts'
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
const i18n = createI18n()
config.global.plugins = [i18n]
// YourComponent.vue
<div id="app">
<p>{{ t("message.hello") }}</p>
</div>
<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>
// component_test.ts
describe('xxx', () => {
it('yyy', () => {
const wrapper = mount(YourComponent);
}
})
请注意,如果您将全局配置用作
$t
,Luckylooke 的答案将有效。
// YourComponent.vue
<div id="app">
<p>{{ $t("message.hello") }}</p>
</div>
// tests/unit.setup.ts
import { config } from "@vue/test-utils"
config.global.mocks = {
$t: tKey => tKey; // just return translation key
};
我阅读了本教程教模拟vue-router,然后我为vue-i18n做了一个类似的解决方案并且它有效。
Component (HelloWorld.vue)
<script setup>
import { useI18n } from "vue-i18n";
const { t } = useI18n();
</script>
<template>
<div class="greetings">
<h1>{{ t("commonsmessagehello") }}</h1>
<h2>{{ t("localhello") }}</h2>
<h2>{{ $t("message.success") }}</h2>
</div>
</template>
<i18n src="../commons/locales.json"></i18n>
<i18n>
{
"enUS": {
"localhello": "local helloooooo"
}
}
</i18n>
Test
import { describe, it, expect, vi } from "vitest";
import { mount, config } from "@vue/test-utils";
import { useI18n } from "vue-i18n";
import HelloWorld from "../HelloWorld.vue";
vi.mock("vue-i18n");
useI18n.mockReturnValue({
t: (tKey) => tKey,
});
config.global.mocks = {
$t: (tKey) => tKey,
};
describe("HelloWorld", () => {
it("renders properly", () => {
const wrapper = mount(HelloWorld, { });
expect(wrapper.text()).toContain("message.success");
});
});
你怎么看,它对
t
和$t
有效。
这不是理想的方式。总有一天我会尝试弄清楚如何在全球范围内为每个测试做这件事。
如果您正在使用组合 API 并且获取
$setup.t
不是函数,这是因为您可能在测试设置中错误地配置了 createI18n
实例:
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false,
allowComposition: true
})
config.global.plugins = [i18n]
请注意,您需要添加
legacy: false
和allowComposition: true
才能使用组合api,否则$setup.t
不会被定义,您将得到$setup.t
不是函数错误。
如果您不使用任何其他 Vue 插件,组合 API 的全局解决方案:
vitest.setup.ts
import { vi } from 'vitest';
vi.mock('vue-i18n', () => ({
useI18n: () => ({
t: (key: string) => key,
d: (key: string) => key,
}),
}));