从i18njs中模拟I18n类,在React Native with Expo中使用Jest进行测试



我试图在React Native with Expo中使用i18n的组件进行测试,但我收到了一个错误,说Jest encountered an unexpected token

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:
/<app-dir>/node_modules/i18n-js/dist/import/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { I18n } from "./I18n";

对于i18n,我将Expo本地化与i18njs一起使用,因此我使用i18nJS。

这是我的实现:

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 };

它适用于我的所有组件,但无法通过我导入该模块的组件测试,例如:

import i18n from '../../../i18n';之后使用i18n

<Text>{i18n.t('keyOfTranslation')}</Text>


我尝试使用模拟i18n-js模块

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;

和其他解决方案,但后来我总是从初始化I18n类(const i18n = new I18n(translations)(中得到错误,错误为:

● Test suite failed to run
TypeError: _i18nJs.I18n is not a constructor
4 | import translations from './translations';
5 |
> 6 | const i18n = new I18n(translations);
|              ^
7 | i18n.locale = Localization.locale.split('-')[0];
8 | i18n.defaultLocale = 'en';
9 | i18n.enableFallback = true;
at Object.<anonymous> (src/i18n/index.ts:6:14)
at Object.<anonymous> (src/components/otherFolder/MyComponent/index.tsx:17:1)

如何解决

为了解决它,我这样做:

jest.config.ts

import { Config } from '@jest/types';
const config: Config.InitialOptions = {
preset: 'jest-expo',
setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)'
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
setupFiles: ['<rootDir>/src/__mocks__/jest.setup.ts'], <-- add this
};
export default config;

在我的src文件夹下,我创建了一个__mocks__文件夹,在它下面,我创建一个名为jest.setup.ts的文件。

后来,我用以下实现创建了文件i18n-js.tsreact-i18next.ts

i18n-js.ts

jest.mock('i18n-js', () => ({
I18n: () => {
return {
t: jest.fn((str: string) => str)
};
}
}));

react-i18next.ts

import { useTranslation } from 'react-i18next';
jest.mock('react-i18next', () => ({
useTranslation: jest.fn()
}));
const tSpy = jest.fn((str) => str);
const useTranslationSpy: any = useTranslation;
useTranslationSpy.mockReturnValue({
t: tSpy,
i18n: {
changeLanguage: () => new Promise(() => {})
}
});

最后,将这些文件导入jest.setup.ts文件:

import './i18n-js';
import './react-i18next';

最新更新