Skip to main content
Version: 29.7

故障排除

呃哦,出了什么问题吗?使用本指南解决 Jest 的问题。

¥Uh oh, something went wrong? Use this guide to resolve issues with Jest.

测试失败但你不知道原因

¥Tests are Failing and You Don't Know Why

尝试使用 Node 内置的 调试支持。在任何测试中放置 debugger; 语句,然后在项目目录中运行:

¥Try using the debugging support built into Node. Place a debugger; statement in any of your tests, and then, in your project's directory, run:

node --inspect-brk node_modules/.bin/jest --runInBand [any other arguments here]
or on Windows
node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand [any other arguments here]

这将在外部调试器可以连接的 Node 进程中运行 Jest。请注意,该进程将暂停,直到调试器连接到它。

¥This will run Jest in a Node process that an external debugger can connect to. Note that the process will pause until the debugger has connected to it.

要在 Google Chrome(或任何基于 Chromium 的浏览器)中进行调试,请打开浏览器并转到 chrome://inspect,然后单击 "打开 Node 专用开发工具",这将为你提供可以连接到的可用节点实例的列表。运行上述命令后,点击终端中显示的地址(通常是 localhost:9229 之类的),就可以使用 Chrome 的 DevTools 来调试 Jest 了。

¥To debug in Google Chrome (or any Chromium-based browser), open your browser and go to chrome://inspect and click on "Open Dedicated DevTools for Node", which will give you a list of available node instances you can connect to. Click on the address displayed in the terminal (usually something like localhost:9229) after running the above command, and you will be able to debug Jest using Chrome's DevTools.

将显示 Chrome 开发者工具,并在 Jest CLI 脚本的第一行设置断点(这样做是为了让你有时间打开开发者工具并防止 Jest 在你有时间执行之前执行) 。单击屏幕右上角看起来像 "play" 按钮的按钮以继续执行。当 Jest 执行包含 debugger 语句的测试时,执行将暂停,你可以检查当前范围和调用堆栈。

¥The Chrome Developer Tools will be displayed, and a breakpoint will be set at the first line of the Jest CLI script (this is done to give you time to open the developer tools and to prevent Jest from executing before you have time to do so). Click the button that looks like a "play" button in the upper right hand side of the screen to continue execution. When Jest executes the test that contains the debugger statement, execution will pause and you can examine the current scope and call stack.

注意

--runInBand cli 选项确保 Jest 在同一进程中运行测试,而不是为单个测试生成进程。通常,Jest 跨进程并行测试运行,但很难同时调试多个进程。

¥The --runInBand cli option makes sure Jest runs the test in the same process rather than spawning processes for individual tests. Normally Jest parallelizes test runs across processes but it is hard to debug many processes at the same time.

在 VS Code 中调试

¥Debugging in VS Code

有多种方法可以使用 Visual Studio 代码 内置 debugger 来调试 Jest 测试。

¥There are multiple ways to debug Jest tests with Visual Studio Code's built-in debugger.

要附加内置调试器,请按上述方式运行测试:

¥To attach the built-in debugger, run your tests as aforementioned:

node --inspect-brk node_modules/.bin/jest --runInBand [any other arguments here]
or on Windows
node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand [any other arguments here]

然后使用以下 launch.json 配置附加 VS Code 的调试器:

¥Then attach VS Code's debugger using the following launch.json config:

{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 9229
}
]
}

要自动启动并附加到运行测试的进程,请使用以下配置:

¥To automatically launch and attach to a process running your tests, use the following configuration:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/.bin/jest",
"--runInBand"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}

或 Windows 的以下内容:

¥or the following for Windows:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/jest/bin/jest.js",
"--runInBand"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}

如果你使用 Facebook 的 create-react-app,你可以使用以下配置调试 Jest 测试:

¥If you are using Facebook's create-react-app, you can debug your Jest tests with the following configuration:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug CRA Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/react-scripts",
"args": [
"test",
"--runInBand",
"--no-cache",
"--env=jsdom",
"--watchAll=false"
],
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}

有关节点调试的更多信息可以找到 此处

¥More information on Node debugging can be found here.

在 WebStorm 中调试

¥Debugging in WebStorm

WebStorm 内置了对 Jest 的支持。阅读 在 WebStorm 中使用 Jest 进行测试 了解更多信息。

¥WebStorm has built-in support for Jest. Read Testing With Jest in WebStorm to learn more.

缓存问题

¥Caching Issues

转换脚本已更改或 Babel 已更新,但 Jest 无法识别这些更改?

¥The transform script was changed or Babel was updated and the changes aren't being recognized by Jest?

使用 --no-cache 重试。Jest 缓存转换后的模块文件以加快测试执行速度。如果你使用自己的自定义转换器,请考虑向其中添加 getCacheKey 函数:Relay 中的 getCacheKey

¥Retry with --no-cache. Jest caches transformed module files to speed up test execution. If you are using your own custom transformer, consider adding a getCacheKey function to it: getCacheKey in Relay.

未解决的 Promise

¥Unresolved Promises

如果 Promise 根本无法解析,则可能会抛出此错误:

¥If a promise doesn't resolve at all, this error might be thrown:

- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.`

最常见的是,这是由 Promise 实现冲突引起的。考虑用你自己的 Promise 实现替换全局 Promise 实现,例如 globalThis.Promise = jest.requireActual('promise'); 和/或将使用的 Promise 库合并到一个库中。

¥Most commonly this is being caused by conflicting Promise implementations. Consider replacing the global promise implementation with your own, for example globalThis.Promise = jest.requireActual('promise'); and/or consolidate the used Promise libraries to a single one.

如果你的测试运行时间较长,你可能需要考虑通过调用 jest.setTimeout 来增加超时

¥If your test is long running, you may want to consider to increase the timeout by calling jest.setTimeout

jest.setTimeout(10_000); // 10 second timeout

Watchman 问题

¥Watchman Issues

尝试使用 --no-watchman 运行 Jest 或将 watchman 配置选项设置为 false

¥Try running Jest with --no-watchman or set the watchman configuration option to false.

另请参阅 值班员故障排除

¥Also see watchman troubleshooting.

Docker 和/或持续集成 (CI) 服务器上的测试极其缓慢。

¥Tests are Extremely Slow on Docker and/or Continuous Integration (CI) server.

虽然 Jest 在大多数情况下在具有快速 SSD 的现代多核计算机上速度极快,但在某些设置上可能会很慢,因为我们的用户 have discovered

¥While Jest is most of the time extremely fast on modern multi-core computers with fast SSDs, it may be slow on certain setups as our users have discovered.

基于 findings,缓解此问题并将速度提高高达 50% 的一种方法是按顺序运行测试。

¥Based on the findings, one way to mitigate this issue and improve the speed by up to 50% is to run tests sequentially.

为此,你可以使用 --runInBand 在同一线程中运行测试:

¥In order to do this you can run tests in the same thread using --runInBand:

# Using Jest CLI
jest --runInBand

# Using your package manager's `test` script (e.g. with create-react-app)
npm test -- --runInBand

在 Travis-CI 等持续集成服务器上加快测试执行时间的另一种替代方法是将最大工作池设置为 ~4。特别是在 Travis-CI 上,这可以将测试执行时间减少一半。注意:适用于开源项目的 Travis CI 免费计划仅包含 2 个 CPU 核心。

¥Another alternative to expediting test execution time on Continuous Integration Servers such as Travis-CI is to set the max worker pool to ~4. Specifically on Travis-CI, this can reduce test execution time in half. Note: The Travis CI free plan available for open source projects only includes 2 CPU cores.

# Using Jest CLI
jest --maxWorkers=4

# Using your package manager's `test` script (e.g. with create-react-app)
npm test -- --maxWorkers=4

如果你使用 GitHub Actions,则可以使用 github-actions-cpu-cores 来检测 CPU 数量,并将其传递给 Jest。

¥If you use GitHub Actions, you can use github-actions-cpu-cores to detect number of CPUs, and pass that to Jest.

- name: Get number of CPU cores
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@v2
- name: run tests
run: yarn jest --max-workers ${{ steps.cpu-cores.outputs.count }}

你可以做的另一件事是使用 shard 标志在多台机器上并行测试运行。

¥Another thing you can do is use the shard flag to parallelize the test run across multiple machines.

coveragePathIgnorePatterns 好像没有什么作用。

¥coveragePathIgnorePatterns seems to not have any effect.

确保你没有使用 babel-plugin-istanbul 插件。Jest 封装了 Istanbul,因此也告诉 Istanbul 需要使用覆盖范围收集来检测哪些文件。当使用 babel-plugin-istanbul 时,Babel 处理的每个文件都会有覆盖率收集代码,因此它不会被 coveragePathIgnorePatterns 忽略。

¥Make sure you are not using the babel-plugin-istanbul plugin. Jest wraps Istanbul, and therefore also tells Istanbul what files to instrument with coverage collection. When using babel-plugin-istanbul, every file that is processed by Babel will have coverage collection code, hence it is not being ignored by coveragePathIgnorePatterns.

定义测试

¥Defining Tests

必须同步定义测试,Jest 才能收集你的测试。

¥Tests must be defined synchronously for Jest to be able to collect your tests.

作为说明为什么会出现这种情况的示例,假设我们编写了一个如下测试:

¥As an example to show why this is the case, imagine we wrote a test like so:

// Don't do this it will not work
setTimeout(() => {
it('passes', () => expect(1).toBe(1));
}, 0);

当 Jest 运行测试来收集 test 时,它不会找到任何东西,因为我们已将定义设置为在事件循环的下一个时钟周期异步发生。这意味着当你使用 test.each 时,你无法在 beforeEach / beforeAll 内异步设置表。

¥When Jest runs your test to collect the tests it will not find any because we have set the definition to happen asynchronously on the next tick of the event loop. This means when you are using test.each you cannot set the table asynchronously within a beforeEach / beforeAll.

仍未解决?

¥Still unresolved?

参见 帮助

¥See Help.