如何解决在运行Jest测试时出现的“Cannot use import statement outside a module”的问题?

335

我有一个使用TypeScript、Jest、Webpack和Babel构建的React应用程序(不使用Create React App)。在尝试运行yarn jest时,我收到以下错误:

jest error

我尝试过删除所有软件包并重新添加它们,但这并不能解决问题。我查看了类似的问题和文档,但仍然不理解其中的某些内容。我甚至按照另一个从头设置此环境的指南,仍然在我的代码中遇到了这个问题。

依赖项包括...

"dependencies": {
  "@babel/plugin-transform-runtime": "^7.6.2",
  "@babel/polyfill": "^7.6.0",
  "babel-jest": "^24.9.0",
  "react": "^16.8.6",
  "react-dom": "^16.8.6",
  "react-test-renderer": "^16.11.0",
  "source-map-loader": "^0.2.4"
},
"devDependencies": {
  "@babel/core": "^7.6.0",
  "@babel/preset-env": "^7.6.0",
  "@babel/preset-react": "^7.0.0",
  "@types/enzyme": "^3.9.2",
  "@types/enzyme-adapter-react-16": "^1.0.5",
  "@types/jest": "^24.0.13",
组件的导入行...
import * as React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import HomePage from "./components/pages";
import {
  Footer,
  Header,
  Navigation,
} from "./components/shared";

测试文件包含用于验证软件或系统功能的测试套件和用例。 在开发过程中,经常需要运行测试以确保代码或产品符合预期。 测试文件还可以包括结果报告和其他有关测试执行的信息。

import * as React from "react";
import * as renderer from "react-test-renderer";
import App from "../App";

it("Renders the Footer correctly", () => {
  const tree = renderer
    .create(<App />)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

我希望在我的组件中使用具名导入而不会导致我的测试失败。如果我只在整个解决方案中使用默认导入,似乎可以修复此问题,但我更希望不采用这种方法。


2
顺便提一下,当我为Jest设置自定义TestSequencer时遇到了这个问题,我只是在这个文件中切换到使用require而不是import - Joshua Pinter
这可能是由于环境变量问题引起的。请参见我的其他相关答案:https://dev59.com/Aqfja4cB1Zd3GeqP2uMm#63749183 - Bence Szalai
如果有人目前遇到这个问题,这个解决方案在我的情况下修复了这个错误。https://github.com/react-hook-form/resolvers/issues/396#issuecomment-1114248072 - diemondtank
@diemondtank,这显然是一个特定于包(hookform)的解决方案。我在resolver.js中看到了if (pkg.name === '@hookform/resolvers') - 丶 Limeー来夢 丶
这似乎是Jest中的一个错误引起的:https://github.com/facebook/jest/issues/8365 - Elias Zamaria
28个回答

2
在主目录下创建.babelrc文件,并添加以下代码,然后安装这些包@babel/core、@babel/preset-env和@babel/preset-react。
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": "commonjs"
      }
    ],
    "@babel/preset-react"
  ]
}

"modulejs": "commonjs"添加到我的代码中解决了这个问题。 - tjvg1991

1
对于我来说,将文件重命名为babel.config.js起作用了。这是我的配置文件,使用TypeScript的NX项目和Twin-macro插件。

// .babelrc.js >> babel.config.js
module.exports = {
  presets: [
    [
      "@nrwl/react/babel",
      {
        "runtime": "automatic",
        "targets": {
          "browsers": [">0.25%", "not dead"]
        },
        "preset-react": {
          runtime: "automatic",
          importSource: "@emotion/react",
        },
      }
    ],
    '@babel/preset-env',
    '@emotion/babel-preset-css-prop',
    '@babel/preset-typescript'
  ],
  plugins: ['@emotion', 'macros', '@babel/plugin-transform-runtime', 'react-docgen'],
}


此外,请注意即使更新了package.json,也可以工作。有关详细信息,请参见https://kulshekhar.github.io/ts-jest/docs/getting-started/presets/#basic-usage
// package.json
"jest": {
    // Replace `ts-jest` with the preset you want to use
    // from the above list
    "preset": "ts-jest"
  }

1

我需要做一些事情才能让它对我起作用

  1. 将我的.babelrc重命名为babel.config.js并进行一些小修改:
// .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3.26",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react"
  ],
  ...
}

// babel.config.js - This still works fine with webpack
module.exports = {
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3.26",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react"
  ],
  ...
}

请将以下内容添加到我的jest配置文件中:
{
  ...  
  "transformIgnorePatterns": [
    "node_modules/(?!(react-leaflet-custom-control)/)"
  ],
  ...
}

其中react-leaflet-custom-control是导致我问题的包。


1

匹配文件扩展名:

我在根目录下导入了一个名为Todo.jsx的文件,路径为./src/Todo/。每当我将其更改为Todo.js时,问题就解决了。

免责声明:我不确定组件文件扩展名为jsxjs的要求是什么。这对我没有影响,但我想象它可能会影响智能感知或代码片段。


0
问题可能是jest不支持原生esmodules,这可能会导致问题,如果你的typescript目标是es6或更高版本。
如果您正在测试构建的typescript输出,您可以在转译时简单地添加一个module=commonjs标志。这样,您的代码可以在es6或更高版本下运行,并且仍然可以与Jest一起使用。
"scripts": {
  "test": tsc --module commonjs && jest {your-output-folder}/
}

这很棒的是,我不需要添加任何额外的babel依赖项或特殊的jest运行程序 :)


0

我通过更改我的 tsconfig.json 文件以获得兼容的本机输出来解决了这个问题。

"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */

并非在每种情况下都是理想的,但您可能对此感到满意。


0

个人而言,我按照 @ajwl 的设置进行了操作,但发现在 jest.config.js 文件的 setupFiles: 部分中使用的 jsdom-worker 触发了相同的错误。一旦移除,我的测试通过了。

P.S. 我的 babel.config.js 有点不同,因为我有一个 Vuejs(v2) 单页应用程序(与 Vitejs 打包在一起):

module.exports = {
  plugins: ['@babel/plugin-transform-modules-commonjs'],
  presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
}

0
我的问题出在Next.js的13版本上。这个GitHub的问题引导我找到了正确的解决方法https://github.com/vercel/next.js/issues/36077#issuecomment-1096635363
module.exports = async () => ({
    ...await createJestConfig(customJestConfig)(),
    // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
    transformIgnorePatterns: [
        'node_modules/(?!(query-string|decode-uri-component|split-on-first|filter-obj|crypto-es|strict-uri-encode)/)',
        '^.+\\.module\\.(css|sass|scss)$',
    ]
});

在我的情况下,查询字符串是问题包,它还需要忽略其他包。

0

没有任何答案能够帮助我,真正帮助我的是确保我的NODE_ENV设置为测试环境,因为babel配置是基于NODE_ENV的,如果不小心使用了错误的NODE_ENV并且没有在babel配置中进行配置,那么你将无法使用babel,typescript文件也将无法被转换。

我花了几个小时才弄清楚这个问题,所以我希望它能够节省其他人的时间。


0

不知道为什么以及如何解决问题,但我解决问题的方法非常有趣。 只需在您的src文件夹中添加__mocks__文件夹,并在__mocks__文件夹内创建一个名为axios.js的空文件即可。


手动模拟 - 1sina1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接