You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在react-i18next中对t函数进行spy监听以测试其参数与返回值

国际化t函数调用与返回值测试方案

核心思路

要同时拿到t函数的入参和返回值,需要创建保留原翻译能力的间谍函数:既不破坏原t函数的翻译逻辑(确保返回值符合国际化配置),又能捕获每次调用的入参和返回结果用于断言。

Jest + react-i18next 实现示例

前置配置:初始化测试用i18n实例

先在测试文件中初始化i18n,加载你需要用到的国际化配置:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

// 测试用国际化资源,和你实际的配置保持一致
const testTranslations = {
  some: {
    key: "Hi {{name}}"
  }
};

i18n
  .use(initReactI18next)
  .init({
    lng: 'zh-CN',
    resources: {
      'zh-CN': { translation: testTranslations }
    },
    fallbackLng: 'zh-CN',
    interpolation: { escapeValue: false }
  });

创建带翻译能力的间谍函数

根据你使用t函数的方式二选一即可:

// 方式1:直接监听全局导入的t函数
import * as i18nModule from 'i18next';
const tSpy = jest.spyOn(i18nModule, 't');

// 方式2:监听useTranslation hook返回的t(React项目更常用)
import { useTranslation } from 'react-i18next';
jest.mock('react-i18next', () => ({
  ...jest.requireActual('react-i18next'),
  useTranslation: jest.fn()
}));
// 间谍函数内部调用原t方法,保留翻译能力
const mockT = jest.fn((key, options) => i18n.t(key, options));
useTranslation.mockReturnValue({ t: mockT, i18n });

执行断言

在组件渲染/业务逻辑执行完成后,调用断言即可:

// 注意原示例中的 toHaveBeenCaledWith 存在拼写错误,正确写法如下
expect(mockT).toHaveBeenCalledWith("some.key", { name: "Ash" });
expect(mockT).toHaveReturnedWith("Hi Ash");

Vitest 适配方案

逻辑和Jest完全一致,仅需替换对应的API前缀即可:

// 替换jest为vi
import * as i18nModule from 'i18next';
const tSpy = vi.spyOn(i18nModule, 't');

// mock hook的写法同理
vi.mock('react-i18next', () => ({
  ...vi.importActual('react-i18next'),
  useTranslation: vi.fn()
}));
const mockT = vi.fn((key, options) => i18n.t(key, options));
useTranslation.mockReturnValue({ t: mockT, i18n });

注意事项

  • 不要直接把t函数mock为空函数,必须保留原翻译逻辑,否则无法拿到正确的返回值做toHaveReturnedWith断言
  • 多语言场景可以在测试用例前修改i18n.lng的值,即可测试不同语言下的返回值是否符合预期
  • 异步组件/逻辑需要等待执行完成后再做断言,避免捕获不到调用记录

内容的提问来源于stack exchange,提问作者narukaioh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:36:01