如何对react-i18next的useTranslation钩子使用Jest mockImplementation?
问题根因
jest.mock 存在内置的变量提升机制,执行优先级高于所有普通的变量声明、赋值操作。你代码中jest.mock的工厂函数执行时,const mockTranslation = jest.fn(...)这行赋值代码还没运行,此时工厂函数内引用的mockTranslation实际为undefined,相当于你给t赋值了undefined,调用自然不会按照你预期的逻辑返回结果。
你能捕获到调用参数的情况,大概率是你在测试用例执行阶段又额外给t赋值了mock函数,但没有同步绑定返回逻辑,才会出现调用记录存在、返回值为undefined的现象。
解决方案
方案1:最简适配变量替换的mock写法
如果仅需要t函数支持变量替换、可查看调用记录,直接在jest.mock内部定义mock逻辑即可,无需额外声明外部变量:
jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: jest.fn((key, options = {}) => { // 基础变量替换逻辑,可根据需求调整 return Object.entries(options).reduce((translated, [placeholder, value]) => { return translated.replaceAll(`{{${placeholder}}}`, value) }, key) }) }) }))
测试用例中可直接导入useTranslation拿到mock的t函数查看调用记录:
import { useTranslation } from 'react-i18next' test('组件翻译调用符合预期', () => { render(<YourComponent />) const { t } = useTranslation() // 验证调用参数 expect(t).toHaveBeenCalledWith('your.translation.key', { name: 'test' }) })
方案2:需要外部单独控制mock实现的写法
如果需要在多个测试用例中动态修改t函数的返回值,可在mock定义后,每次测试前手动覆盖useTranslation的返回值:
// 先mock模块结构 jest.mock('react-i18next', () => ({ useTranslation: jest.fn(() => ({ t: jest.fn() })) })) // 外部声明可自定义的mock函数 const mockT = jest.fn(key => key) beforeEach(() => { // 每次测试前绑定最新的mock实现 useTranslation.mockReturnValue({ t: mockT }) // 可重置调用记录 mockT.mockClear() })
内容的提问来源于stack exchange,提问作者dajoto
相关产品推荐
相关产品推荐

