Vue.js 3测试报错TypeError: $setup.t is not a function,求解决方案
Vue3 + Vue-i18n 测试时Mock t函数的解决方案
问题背景
在Vue.js 3项目中使用<script setup>、TypeScript和vue-i18n,测试采用Vitest+Vue Testing Library。尝试mock i18n的t函数时,组件抛出错误:
TypeError: $setup.t is not a function
用户的测试代码如下:
import { describe, test, expect } from "vitest"; import { render } from "@testing-library/vue"; import TheError from "@/components/TheError.vue"; describe("TheError", () => { test("Renders error message", () => { const message = "Something went wrong!"; const t = (msg: string): string => msg; const wrapper = render(TheError, { props: { message }, global: { mocks: { t }, }, }); const errorMessage = wrapper.getByText(message); expect(errorMessage.textContent).toBe(message); }); });
原因分析
在<script setup>语法中,vue-i18n的t函数是通过useI18n()钩子获取的局部函数,并非挂载到Vue全局的$t方法。直接在测试的global.mocks中声明t,无法覆盖组件内部通过useI18n()获取的t,因此会出现函数不存在的错误。
解决方案
通过Vitest的vi.mock方法mockvue-i18n的useI18n钩子,让它返回包含自定义t函数的对象,这样组件就能获取到mock后的t函数。
基础Mock方案
修改后的测试代码如下:
import { describe, test, expect, vi } from "vitest"; import { render } from "@testing-library/vue"; import { useI18n } from "vue-i18n"; // Mock useI18n钩子 vi.mock("vue-i18n", () => ({ useI18n: vi.fn(() => ({ t: (msg: string) => msg // 自定义mock的t函数 })) })); import TheError from "@/components/TheError.vue"; describe("TheError", () => { test("Renders error message", () => { const message = "Something went wrong!"; const wrapper = render(TheError, { props: { message }, }); const errorMessage = wrapper.getByText(message); expect(errorMessage.textContent).toBe(message); }); });
动态修改Mock返回值
如果需要针对不同测试用例返回不同的t函数结果,可以在测试用例内部动态修改mock的返回值:
test("Renders translated error message", () => { const mockMsg = "Translated error!"; // 修改useI18n的mock返回值 (useI18n as vi.Mock).mockReturnValue({ t: () => mockMsg }); const wrapper = render(TheError, { props: { message: "error.key" }, }); expect(wrapper.getByText(mockMsg)).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Explicit
相关产品推荐
相关产品推荐

