使用 Jest 和 @testing-library/react-native 测试 React Native 项目时出现“SyntaxError:无法在模块外部使用 import 语句”错误?

Ben*_*tes 10 testing jestjs react-native react-native-testing-library

每当我运行时都会出现错误npm test

\n
 FAIL  ./App.test.js\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x97\x8f 测试套件运行失败

\n
Jest encountered an unexpected token\n\nThis usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.\n\nBy default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".\n\nHere's what you can do:\n \xe2\x80\xa2 If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.\n \xe2\x80\xa2 To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.\n \xe2\x80\xa2 If you need a custom transformation specify a "transform" option in your config.\n \xe2\x80\xa2 If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.\n\nYou'll find more details and examples of these config options in the docs:\nhttps://jestjs.io/docs/en/configuration.html\n\nDetails:\n\n/Users/bestes/Desktop/react-native-training/node_modules/react-native-status-bar-height/index.js:1\n({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { Dimensions, Platform, StatusBar } from 'react-native';\n                                                                                         ^^^^^^\n\nSyntaxError: Cannot use import statement outside a module\n\n  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)\n  at Object.<anonymous> (node_modules/react-native-elements/src/config/index.js:1:1)\n
Run Code Online (Sandbox Code Playgroud)\n

我的测试:

\n
import 'react-native';\nimport React from 'react';\nimport { render } from '@/../testing/test-utils'\nimport App from './App'\n\n\ntest('should render app component', () => {\n  const result = render(<App />)\n\n  expect(result).toMatchSnapshot()\n})\n
Run Code Online (Sandbox Code Playgroud)\n

我的 test-utils.js 文件:

\n
import React from 'react'\n\nimport { render } from '@testing-library/react-native'\nimport { store } from '@/bootstrap/redux'\nimport { Provider } from 'react-redux'\n\nconst AllTheProviders = ({ children }) => {\n  return (\n    <Provider store={store}>\n      {children}\n    </Provider>\n  )\n}\n\nconst customRender = (ui, options) =>\n  render(ui, { wrapper: AllTheProviders, ...options })\n\n// re-export everything\nexport * from '@testing-library/react-native'\n\n// override render method\nexport { customRender as render }\n
Run Code Online (Sandbox Code Playgroud)\n

我的 package.json 文件:

\n
{\n  "name": "ReactNativeTraining",\n  "version": "0.0.1",\n  "private": true,\n  "scripts": {\n    "android": "react-native run-android",\n    "ios": "react-native run-ios",\n    "start": "react-native start",\n    "test": "jest",\n    "lint": "eslint ."\n  },\n  "dependencies": {\n    "@react-native-community/geolocation": "2.0.2",\n    "@react-native-community/masked-view": "0.1.10",\n    "@react-native-picker/picker": "1.9.10",\n    "@reduxjs/toolkit": "1.5.0",\n    "axios": "0.21.1",\n    "dayjs": "1.10.4",\n    "lodash": "4.17.20",\n    "react": "16.13.1",\n    "react-native": "0.63.2",\n    "react-native-config": "1.4.2",\n    "react-native-elements": "3.0.0-alpha.1",\n    "react-native-geocoding": "0.5.0",\n    "react-native-gesture-handler": "1.9.0",\n    "react-native-permissions": "3.0.0",\n    "react-native-picker-select": "8.0.4",\n    "react-native-reanimated": "1.13.2",\n    "react-native-safe-area-context": "3.1.9",\n    "react-native-screens": "2.17.0",\n    "react-native-size-matters": "0.4.0",\n    "react-native-vector-icons": "8.0.0",\n    "react-navigation": "4.0.2",\n    "react-navigation-stack": "1.5.4",\n    "react-navigation-tabs": "2.4.1",\n    "react-redux": "7.2.2"\n  },\n  "devDependencies": {\n    "@babel/core": "7.12.10",\n    "@babel/runtime": "7.12.5",\n    "@react-native-community/eslint-config": "2.0.0",\n    "@testing-library/jest-native": "4.0.1",\n    "@testing-library/react-native": "7.2.0",\n    "babel-jest": "^26.6.3",\n    "babel-plugin-module-resolver": "4.0.0",\n    "eslint": "7.18.0",\n    "jest": "26.6.3",\n    "metro-react-native-babel-preset": "0.64.0",\n    "react-test-renderer": "16.13.1"\n  },\n  "type": "module",\n  "jest": {\n    "verbose": true,\n    "preset": "react-native",\n    "setupFilesAfterEnv": ["@testing-library/jest-native/extend-expect"],\n    "transformIgnorePatterns": [\n      "node_modules/(?!(react-native",\n      "@react-native-community/geolocation",\n      "@react-native-community/masked-view",\n      "|@react-native-picker/picker",\n      "|@reduxjs/toolkit",\n      "|axios",\n      "|dayjs",\n      "|lodash",\n      "|react",\n      "|react-native",\n      "|react-native-config",\n      "|react-native-elements",\n      "|react-native-geocoding",\n      "|react-native-gesture-handler",\n      "|react-native-permissions",\n      "|react-native-picker-select",\n      "|react-native-reanimated",\n      "|react-native-safe-area-context",\n      "|react-native-screens",\n      "|react-native-size-matters",\n      "|react-native-vector-icons",\n      "|react-navigation",\n      "|react-navigation-stack",\n      "|react-navigation-tabs",\n      "|react-redux",\n      ")/)"\n    ]\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我的 babel.config.js 文件:

\n
module.exports = function (api) {\n  api.cache(true)\n  const presets = [\n    'module:metro-react-native-babel-preset'\n  ]\n  const plugins = [\n    [\n      'module-resolver', {\n        'root': ['./src/'],\n        'extensions': ['.js', '.ios.js', '.android.js'],\n        'alias': {\n          '@': './src/'\n        }\n      }\n    ]\n  ]\n  return {\n    presets,\n    plugins\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我尝试过的操作:\n将 "type": "module" 添加到我的根级别 package.json 文件,这修复了导出时的类似错误,\n将 Transform Ignore Patterns 添加到 package.json 文件中的 Jest 键。\nI我将所有依赖项添加到了transformIgnorePatterns中,因为它一直在每个依赖项上抛出错误,直到我添加了所有依赖项,现在它在react-native模块导入上抛出错误。

\n

小智 2

[已解决]为我工作安装如下

npm install --save-dev @babel/core @babel/preset-env
Run Code Online (Sandbox Code Playgroud)

之后在根目录中创建“babel.config.js”文件,内容应如下所示

module.exports = {
  presets: ['@babel/preset-env', '@babel/preset-react'],
  env: {
    test: {
      plugins: ["@babel/plugin-transform-runtime"]
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 它不能解决反应本机项目的问题。从 0.63.3 升级到 0.66.3 突然导致一些测试因这个奇怪的错误而中断。 (6认同)
  • @philk 我在 GitHub 上找到了有关该问题的讨论。那里提到的修复适用于 React Native 0.64.0+。从 0.63.4 升级后,我在 0.66.4 上测试了它,它对我有帮助。https://github.com/facebook/react-native/issues/31190#issuecomment-822586986 (2认同)