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

配置ESM的Jest无法解析React Native组件导入,求助排查

问题:Jest配置ESM测试React Native组件时无法解析'react-native'导出

报错信息

SyntaxError: The requested module 'react-native' does not provide an export named 'StyleSheet'

环境版本

React Native: 0.70.4

代码示例

待测试组件

import React, { ReactElement } from 'react';

import { StyleSheet, Text, View } from 'react-native';

const { container } = StyleSheet.create({
  container: {
    padding: 50,
  },
});

const ThisComponent = (): ReactElement => (
  <View style={container}>
    <Text>Hello World!</Text>
  </View>
);

export default ThisComponent;

测试代码

import React, { ReactElement } from 'react';
import { render } from '@testing-library/react-native';

import ThisComponent from '../ThisComponent';

describe('<OTPInputs>', () => {
  test('Renders without exploding', async () => {
    const { getByText } = render(
      <ThisComponent />,
    );

    expect(getByText('Hello World!')).not.toBeDisabled();
  });
});

Jest配置(package.json)

"jest": {
  "haste": {
    "defaultPlatform": "ios",
    "platforms": [
      "android",
      "ios",
      "native"
    ]
  },
  "resetMocks": true,
  "testEnvironment": "node",
  "testMatch": [
    "**/src/**/*.(spec|test).[tj]s?(x)"
  ],
  "preset": "ts-jest/presets/default-esm",
  "transform": {
    "^.+\\.js$": "babel-jest"
  },
  "transformIgnorePatterns": [
    "node_modules/(?!((jest-)?react-native|@react-native(-community)?)/)"
  ],
  "extensionsToTreatAsEsm": [
    ".ts",
    ".tsx"
  ],
  "globals": {
    "ts-jest": {
      "useESM": true
    }
  },
  "setupFiles": [
    "<rootDir>/node_modules/react-native/jest/setup.js"
  ],
  "setupFilesAfterEnv": [
    "@testing-library/jest-native/extend-expect"
  ],
  "moduleNameMapper": {
    "^~/(.*)$": "<rootDir>/src/$1",
    "^~components/(.*)$": "<rootDir>/src/components/$1",
    "^~util/(.*)$": "<rootDir>/src/util/$1",
    "^~types/(.*)$": "<rootDir>/src/types/$1"
  }
}

问题原因

React Native 0.70.x的主导出文件是使用特殊语法的CommonJS(CJS)格式,而ESM模式下的Jest对CJS导出的解析逻辑与常规ESM不同,无法正确识别StyleSheet、Text这类命名导出,从而抛出错误。

解决方案

方案1:手动Mock React Native的ESM兼容导出

使用jest.unstable_mockModule模拟符合ESM规范的react-native导出,同时测试代码需改为动态导入组件:

步骤1:添加Mock代码

在测试文件顶部添加以下mock:

jest.unstable_mockModule('react-native', () => ({
  __esModule: true,
  StyleSheet: jest.requireActual('react-native/Libraries/StyleSheet/StyleSheet'),
  Text: jest.requireActual('react-native/Libraries/Text/Text'),
  TextInput: jest.requireActual('react-native/Libraries/Components/TextInput/TextInput'),
  TouchableOpacity: jest.requireActual('react-native/Libraries/Components/Touchable/TouchableOpacity'),
  View: jest.requireActual('react-native/Libraries/Components/View/View'),
}));

步骤2:修改测试代码的组件导入方式

将静态导入改为动态导入:

// 替换原静态导入
const ThisComponent = (await import('../ThisComponent')).default;

修改后的完整测试代码:

import React from 'react';
import { render } from '@testing-library/react-native';

jest.unstable_mockModule('react-native', () => ({
  __esModule: true,
  StyleSheet: jest.requireActual('react-native/Libraries/StyleSheet/StyleSheet'),
  Text: jest.requireActual('react-native/Libraries/Text/Text'),
  TouchableOpacity: jest.requireActual('react-native/Libraries/Components/Touchable/TouchableOpacity'),
  View: jest.requireActual('react-native/Libraries/Components/View/View'),
}));

describe('<ThisComponent>', () => {
  test('Renders without exploding', async () => {
    const ThisComponent = (await import('../ThisComponent')).default;
    const { getByText } = render(<ThisComponent />);

    expect(getByText('Hello World!')).not.toBeDisabled();
  });
});

方案2:调整Jest配置适配RN的CJS导出

将Jest预设改回React Native官方预设,同时保留TS的ESM支持:

  1. 修改preset为'react-native'
  2. 调整globals中的ts-jest配置,确保兼容RN的处理逻辑

修改后的Jest配置片段:

"jest": {
  // ...其他配置不变
  "preset": "react-native",
  "globals": {
    "ts-jest": {
      "useESM": true,
      "tsconfig": "tsconfig.spec.json" // 可指定测试专用tsconfig
    }
  },
  // ...其他配置不变
}

注意:使用官方预设时,需确保transformIgnorePatterns已正确包含react-native相关包,避免未转译的代码导致错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:56:04