如何解决React Testing Library中搭配Suspense的i18n无法加载问题
问题原因
- 异常本质是测试环境下i18n翻译资源未完成预加载,
useTranslationhook 持续触发Suspense挂起逻辑 - 你给
ProjectNavigation传入的useSuspense={false}未生效,是因为该参数需要传入useTranslationhook 本身,而非组件props,未做透传的情况下该配置不会被i18n识别
解决方案
下面提供三种可直接落地的修复方案,按需选择即可:
方案1:修改测试环境全局i18n配置(最推荐,适配所有用例)
在Jest测试的全局初始化文件(通常为jest.setup.js/setupTests.js)中调整i18n初始化配置,关闭全局Suspense、直接传入翻译资源避免异步加载:
import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; i18n .use(initReactI18next) .init({ resources: { // 直接传入测试用的翻译资源,不要走异步加载 zh: { translation: require('../public/locales/zh/translation.json') } }, lng: 'zh', fallbackLng: 'zh', react: { // 全局关闭测试环境的Suspense useSuspense: false } });
修改后你的原测试代码不需要加Suspense包裹,直接渲染组件即可正常运行。
方案2:修改测试用例为异步查询
如果你不想修改全局配置,可以将同步的getBy查询替换为异步的findBy,等待翻译加载完成、组件渲染后再做断言:
import React from 'react'; import { render, screen } from '@testing-library/react'; import ProjectNavigation from '../pages/ProjectNavigation'; test('Checks to see if project navigation is rendered', async () => { render( <React.Suspense fallback="Loading..."> <ProjectNavigation /> </React.Suspense>, ); // 异步等待导航组件渲染完成 expect(await screen.findByRole('navigation')).toBeVisible(); });
方案3:Mock useTranslation hook
单元测试场景下可以直接mock翻译hook,跳过真实资源加载逻辑:
import React from 'react'; import { render, screen } from '@testing-library/react'; import ProjectNavigation from '../pages/ProjectNavigation'; // mock react-i18next的useTranslation jest.mock('react-i18next', () => ({ useTranslation: () => { return { t: (key) => key, // 直接返回翻译key,也可以自定义返回测试需要的文本 i18n: { changeLanguage: () => new Promise(() => {}) } }; }, Trans: ({ children }) => children })); test('Checks to see if project navigation is rendered', () => { render(<ProjectNavigation />); expect(screen.getByRole('navigation')).toBeVisible(); });
内容的提问来源于stack exchange,提问作者Henrik Moe Wæhre
相关产品推荐
相关产品推荐

