集成gatsby-theme-i18n后,Gatsby+Jest测试报themeI18N未定义如何解决?
解决Gatsby + Jest测试中gatsby-theme-i18n的
useLocalization钩子报错问题 我刚好遇到过类似的问题,给你分享下解决思路和具体步骤:
问题复盘
你遇到的TypeError: Cannot read property 'themeI18N' of undefined报错,本质是因为Jest是离线测试环境,不会执行Gatsby的静态查询构建流程。gatsby-theme-i18n的useLocalization钩子依赖useStaticQuery获取站点的国际化配置,但Jest默认无法提供这些数据,导致钩子调用失败。
核心解决方案:Mock useStaticQuery的返回值
我们需要手动Mock Gatsby的useStaticQuery函数,返回gatsby-theme-i18n所需的themeI18N结构,让钩子能拿到正确的数据。
步骤1:创建Gatsby的Mock文件
在项目根目录新建__mocks__/gatsby.js文件,内容如下:
import * as React from 'react'; // 模拟useStaticQuery返回gatsby-theme-i18n需要的国际化配置 const useStaticQuery = jest.fn(() => ({ themeI18N: { defaultLocale: 'en', // 替换成你的默认语言 locales: ['en', 'zh'], // 替换成你的支持语言列表 config: { en: { label: 'English', href: '/en/', }, zh: { label: '中文', href: '/zh/', }, }, }, })); // 如果你的项目还用到其他Gatsby钩子(比如useSiteMetadata),也可以在这里一并Mock export { useStaticQuery };
步骤2:调整测试代码
确保测试中正确提供@reach/router的Location上下文,同时让Mock生效。修改后的测试示例:
import React from 'react'; import { render, screen } from '@testing-library/react'; import { Location } from '@reach/router'; import Header from '../components/Header'; describe('<Header />', () => { it('渲染语言切换按钮并能正常显示', () => { render( <Location location={{ pathname: '/en/' }}> <Header /> </Location> ); // 验证语言选项是否存在 expect(screen.getByText('中文')).toBeInTheDocument(); expect(screen.getByText('English')).toBeInTheDocument(); }); });
步骤3:确保Jest配置正确
继续保留你之前添加的transformIgnorePatterns,避免gatsby-theme-i18n被Jest忽略转译:
{ "transformIgnorePatterns": ["node_modules/(?!(gatsby-theme-i18n|gatsby)/)"] }
额外优化:Mock LocalizedLink(可选)
如果LocalizedLink在测试中还有其他依赖问题,也可以单独Mock它,简化测试逻辑:
在__mocks__/gatsby-theme-i18n/index.js中添加:
import React from 'react'; import { Link } from 'gatsby'; // 将LocalizedLink模拟成普通的Gatsby Link const LocalizedLink = ({ to, ...props }) => <Link to={to} {...props} />; export { LocalizedLink };
这样就能完全模拟出国际化环境下的组件行为,让测试正常通过了。
内容的提问来源于stack exchange,提问作者GGrassiant
相关产品推荐
相关产品推荐

