使用 Vitest 时在 vue3 组件中模拟/存根 vue-i18n 翻译的最佳方法

问题描述 投票:0回答:6

我已经开始用 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"

谢谢!

unit-testing vuejs3 vue-i18n vitest
6个回答
4
投票
import { createI18n } from 'vue-i18n';

describe('xxx', () => {
   it('yyy', () => {
      const i18n = createI18n({
         messages: {
            gb: {},
            nl: {},
            ...
         }
      });
      
      const wrapper = mount(YourComponent, {
         global: {
            plugins: [i18n]
         }
      });
   }
})

4
投票

我想你想在全球范围内模拟这个,不需要在每个测试套件中放置相同的代码。

// 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
};

2
投票

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
};

1
投票

我阅读了本教程教模拟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
有效。

这不是理想的方式。总有一天我会尝试弄清楚如何在全球范围内为每个测试做这件事。


0
投票

如果您正在使用组合 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
不是函数错误。


0
投票

如果您不使用任何其他 Vue 插件,组合 API 的全局解决方案:

vitest.setup.ts

import { vi } from 'vitest';

vi.mock('vue-i18n', () => ({
  useI18n: () => ({
    t: (key: string) => key,
    d: (key: string) => key,
  }),
}));
© www.soinside.com 2019 - 2024. All rights reserved.