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

React Native Expo中Jest测试i18n-js报错的解决方法求助

Expo React Native 中 i18n-js + Jest 测试报错解决方案

我在基于Expo的React Native项目里,用i18n-js结合Expo Localization实现了国际化,业务组件运行正常,但用Jest测试引入i18n模块的组件时,先触发「Jest encountered an unexpected token」错误,尝试mock i18n-js模块后又出现「TypeError: _i18nJs.I18n is not a constructor」错误,求解决办法。


一、初始报错信息

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html

Details:

//node_modules/i18n-js/dist/import/index.js:1
({"Object.":function(module,exports,require,__dirname,__filename,global,jest){export { I18n } from "./I18n";

二、i18n 实现代码

import * as Localization from 'expo-localization';
import { I18n } from 'i18n-js';

import translations from './translations';

const i18n = new I18n(translations);
i18n.locale = Localization.locale.split('-')[0];
i18n.defaultLocale = 'en';
i18n.enableFallback = true;

export default i18n;
export { Localization };

三、尝试的Mock配置及后续报错

jest.config.ts 配置

moduleNameMapper: {
    'i18n-jss': '<rootDir>/src/__mocks__/i18n-jsMocked.ts'
  }

i18n-jsMocked.ts 代码

import * as origininalI18n from 'i18n-js';
const mocked = origininalI18n as jest.Mocked<typeof origininalI18n>;
export const I18n = mocked.I18n;

beforeEach(() => {
  I18n.mockClear();
});

const i18nMocked = jest.mock('i18n-js', () => {
  return {
    I18n
  };
});

export default i18nMocked;

触发的构造函数错误

● Test suite failed to run

TypeError: _i18nJs.I18n is not a constructor

import translations from './translations';
const i18n = new I18n(translations);
^
i18n.locale = Localization.locale.split('-')[0];
i18n.defaultLocale = 'en';
i18n.enableFallback = true;

at Object. (src/i18n/index.ts:6:14)
at Object. (src/components/otherFolder/MyComponent/index.tsx:17:1)


四、解决方案

方案1:修复Jest对ES模块的解析问题

初始报错是因为i18n-js发布包使用ES模块语法,Jest默认不对node_modules下的文件转译。修改jest.config.ts的transformIgnorePatterns,让Jest转译i18n-js:

transformIgnorePatterns: [
  'node_modules/(?!(i18n-js|expo-localization)/)'
],

同时确保你的Babel配置(如babel.config.js)支持转译ES模块,比如使用@babel/preset-env和@babel/preset-react。

方案2:正确Mock i18n-js模块

之前的Mock写法有误,需直接构造模拟的I18n类,而非依赖原模块:

  1. 先修正jest.config.ts里的模块匹配错误(原配置写的i18n-jss应为i18n-js):
moduleNameMapper: {
  'i18n-js': '<rootDir>/src/__mocks__/i18n-jsMocked.ts'
}
  1. 重写src/__mocks__/i18n-jsMocked.ts:
// 模拟I18n类,实现必要方法和属性
export class I18n {
  locale: string;
  defaultLocale: string;
  enableFallback: boolean;

  constructor(translations: Record<string, any>) {
    this.locale = 'en';
    this.defaultLocale = 'en';
    this.enableFallback = true;
  }

  // 模拟t方法,直接返回key或自定义值
  t(key: string) {
    return key;
  }
}

export default { I18n };

或用Jest mock函数构造:

const mockI18n = jest.fn().mockImplementation(() => ({
  locale: 'en',
  defaultLocale: 'en',
  enableFallback: true,
  t: (key: string) => key
}));

export const I18n = mockI18n;

export default { I18n };

方案3:Mock整个项目的i18n实例

如果不想Mock底层i18n-js,可直接Mock项目导出的i18n实例,在测试文件顶部添加:

jest.mock('../../i18n', () => ({
  default: {
    t: (key: string) => key
  },
  Localization: {
    locale: 'en-US'
  }
}));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:25:21