从 v29 升级到 v30
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
正在从 Jest v29 升级到 v30?本指南将帮助您重构配置和测试。
完整变更列表请参阅更新日志。
从更旧版本升级?可查看v28升级到v29的指南。
兼容性
-
Jest 30 停止支持 Node 14、16、19 和 21。最低支持版本变更为 Node 18.x。升级前请确保运行环境使用兼容的 Node 版本。
-
TypeScript 最低版本要求提升至 5.4。若使用 Jest(或其任何包)的类型定义,请更新 TypeScript。
-
jest-environment-jsdom包现采用 JSDOM v26。此更新可能导致 DOM 环境行为变化。如遇 DOM 行为差异或新警告,请参考 JSDOM v21–26 版本说明。
Jest Expect 和匹配器
别名匹配器移除
所有匹配器别名已移除,请使用主名称替代。若您仍在使用旧版弃用的匹配器名称,需更新测试代码:
- 已移除别名及对应替代方案:
expect(fn).toBeCalled()→expect(fn).toHaveBeenCalled()expect(fn).toBeCalledTimes(n)→expect(fn).toHaveBeenCalledTimes(n)expect(fn).toBeCalledWith(arg)→expect(fn).toHaveBeenCalledWith(arg)expect(fn).lastCalledWith(arg)→expect(fn).toHaveBeenLastCalledWith(arg)expect(fn).nthCalledWith(n, arg)→expect(fn).toHaveBeenNthCalledWith(n, arg)expect(fn).toReturn()→expect(fn).toHaveReturned()expect(fn).toReturnTimes(n)→expect(fn).toHaveReturnedTimes(n)expect(fn).toReturnWith(val)→expect(fn).toHaveReturnedWith(val)expect(fn).lastReturnedWith(val)→expect(fn).toHaveLastReturnedWith(val)expect(fn).nthReturnedWith(n, val)→expect(fn).toHaveNthReturnedWith(n, val)expect(func).toThrowError(message)→expect(func).toThrow(message)
这些别名方法自 Jest 26 起已被弃用,在 Jest 30 中已彻底移除。请在代码库中全局搜索替换为规范匹配器名称。功能完全一致——仅方法名称变更。(若使用带 eslint-plugin-jest 的 ESLint,no-alias-methods 规则可自动完成替换。)
非可枚举属性
对象匹配器现默认排除非可枚举属性。这可能影响 expect.objectContaining 或相等性检查。
CalledWith 类型推断改进
TypeScript 用户注意:CalledWith 系列匹配器(如 toHaveBeenCalledWith)的类型推断已优化,可更准确推导函数参数类型。多数情况下能更精准捕获类型不匹配问题。这是编译时破坏性变更。
如果你在测试中使用了与实际函数参数类型不匹配的参数进行调用断言,TypeScript 现在可能会在这些测试中报错。例如,如果一个函数的类型定义为接受数字参数,而你写了 expect(fn).toHaveBeenCalledWith("string"),TypeScript 5 + Jest 30 的类型系统将会标记此错误。匹配器的运行时行为并未改变。
要修复这些新的 TypeScript 错误,请确保你的测试参数与函数期望的类型一致(或者,如果你故意使用不同的类型进行调用,可以使用类型转换)。
这项更改不会影响运行时行为,但它可能会暴露你测试中之前未被注意到的类型错误,从而使你的测试更具类型安全性。
配置更新
支持 .mts 和 .cts 文件扩展名
Jest 30 扩展了对 ESM 和 TypeScript 模块文件扩展名的支持:
-
默认的
moduleFileExtensions现在包含了.mts和.cts(TypeScript ESM 和 CommonJS 模块),以及常规扩展名。 -
默认的
testMatch和testRegex模式已更新,现在可以识别.mjs、.cjs、.mts和.cts文件作为测试文件。
如果你的项目中包含这些扩展名的文件,但不打算将它们视为模块或测试文件,你可能需要调整配置。反之,如果你有使用这些扩展名的测试文件,Jest 现在默认会检测到它们(你可以移除之前为了包含它们而添加的自定义配置)。
--testPathPattern 已重命名为 --testPathPatterns
如果你通过路径过滤测试,请注意 CLI 标志已更改:--testPathPattern 标志现在改为 --testPathPatterns。你可以通过用空格分隔模式或重复使用该标志来传递多个模式。例如:
# Old (Jest 29)
jest --testPathPattern="unit/.*"
# New (Jest 30)
jest --testPathPatterns "unit/.*" "integration/.*"
在内部,Jest 会将这些模式合并为一个 TestPathPatterns 对象。如果你之前以编程方式使用 testPathPattern 调用 Jest 的观察模式,现在必须改为构造一个 TestPathPatterns 实例。
移除 --init 命令
交互式配置初始化命令 jest --init 已被移除。这个已弃用的命令曾用于搭建 Jest 配置文件。如果你需要创建配置,可以运行:
npm init jest@latest
# Or for Yarn
yarn create jest
# Or for pnpm
pnpm create jest
其他 CLI 变更
-
Jest 现在会验证需要参数的 CLI 标志,以确保提供了参数。例如,如果你使用
--maxWorkers或--selectProjects,必须包含一个值(例如--maxWorkers=50%)。之前,Jest 可能允许某些标志没有值(回退到默认值);现在如果缺少值,它将抛出错误。请确保任何传递 Jest 标志的脚本或 npm 命令都包含必要的参数。 -
如果你使用
--filter选项来过滤测试文件(这是一种高级用法,你需要提供一个过滤实现的路径),预期的接口已更改。现在,过滤函数应返回一个形如{filtered: Array<string>}的对象,与文档格式一致。在之前的版本中,可能接受不同的返回格式(例如直接返回数组)。请更新所有自定义测试过滤函数,以返回一个带有filtered属性的对象,如文档所述。
测试运行器行为变更
测试中未处理的 Promise 拒绝
Jest 包含了一个修复,以正确处理被拒绝但随后被捕获的 Promise,从而避免错误的测试失败。在 Jest 29 中,一个被异步处理(在测试时间片之后)的 Promise 拒绝仍可能导致测试错误地失败。Jest 30 现在会额外等待一个事件循环的轮次,以确认 Promise 拒绝是否仍然未被处理,然后才会使测试失败。
现在你应该会更少遇到未处理的 Promise 拒绝导致的误报情况。之前因异步处理的拒绝而失败的测试现在应该能通过了。但请注意,这项改动可能会轻微延长测试完成时间,特别是在故意拒绝 Promise 的测试中。为缓解性能影响,我们引入了新的配置标志 waitForUnhandledRejections。如果确实需要恢复之前的行为(不等待),可以禁用此标志。大多数用户无需调整此项——默认设置现在通过防止误报失败来确保正确性。
自定义测试排序器
如果你使用了自定义测试排序器(继承自 Jest 的 TestSequencer 的类),在 Jest 30 中需要进行更新。Jest 现在会向测试排序器传递额外的上下文信息。具体而言,TestSequencer API 已扩展为向你的排序器暴露 globalConfig 和 contexts 属性。
Runtime 中必需的 globalConfig
对于使用 Jest 编程式 API 的用户:现在构造 Runtime 必须提供 globalConfig 参数。如果使用 jest.runCLI 或类似辅助工具,请确保根据更新后的 API 传递所有必需的选项。(标准的 jest CLI 或 npm test 用法不受此变更影响。)
快照与输出变更
修复文档链接更新
已弃用的 goo.gl 短链接从快照测试中移除。此项变更会更新现有快照,将所有 goo.gl 链接替换为完整的原始 URL。
快照中的错误原因链
错误在快照中的序列化方式已变更。Jest 30 的快照序列化器现在会在打印错误时包含 Error 的 cause 属性(如果存在)。
React 空字符串渲染
React 专用快照序列化器不再在输出中渲染空字符串子元素("")。在 Jest 29 中,React 元素里的空字符串子元素可能在快照输出中显示为 "";而在 Jest 30 中将被省略(视为无内容)。
pretty-format 中的对象打印优化
ArrayBuffer 和 DataView 现在会以人类可读的方式打印,而不是显示为包含内部字段的对象。
Jest Mock API 变更
移除 jest.genMockFromModule
旧版函数 jest.genMockFromModule(moduleName) 已被移除。该函数此前已被弃用,推荐使用 jest.createMockFromModule(moduleName) 替代。若你仍在使用 genMockFromModule,请切换到 createMockFromModule——两者功能完全一致。例如:
旧版代码(Jest 29):
const mockFs = jest.genMockFromModule('fs');
新版代码(Jest 30):
const mockFs = jest.createMockFromModule('fs');
移除 Mock 函数类型
以下类型变更仅在你显式导入 Jest API 时适用:
import {expect, jest, test} from '@jest/globals';
部分与 Mock 函数相关的 TypeScript 类型已从公共 API 中移除:
-
MockFunctionMetadata -
MockFunctionMetadataType -
SpyInstance
如果你曾使用 jest.SpyInstance(例如用于标注 jest.spyOn 的返回值),应更新为使用 jest.Spied 类型。
jest.mock 仅支持区分大小写的模块路径
从现在起,jest.mock() 仅支持区分大小写的模块路径。这最多算是一个边缘情况,因为大多数用户会遵循操作系统的文件名模式行为。我们推荐始终使用正确命名的模块路径,以避免将来出现类似的兼容性问题。
旧版代码(Jest 29):
jest.mock('./path/to/FILENAME.js'); // This works EVEN when you only have `filename.js`
新版代码(Jest 30):
jest.mock('./path/to/filename.js'); // This strictly works when you ONLY have `filename.js`
模块与运行时变更
ESM 模块支持与内部重构
Jest 在底层进行了重大变更,涉及软件包的打包和导出方式:
-
Jest 所有内部模块现已打包为单一文件以提升启动速度。这意味着安装 Jest 后加载的文件数量大幅减少(提升性能)。但副作用是任何对 Jest 包的非官方深层导入可能失效。例如,若您曾使用类似
require('jest-runner/build/testWorker')的路径(非公开 API),该路径将不复存在。解决方案: 仅使用 Jest 的公开 API 或文档化接口。若您依赖的内部模块应成为公开 API,请提交 Pull Request 将其暴露。 -
Jest 包现在提供 ESM 包装层。这是支持在 ESM 环境下运行 Jest 的持续改进工作。所有官方 Jest 包都通过
package.json的"exports"字段正确导出自身。对大多数用户而言,这没有直接影响——您仍可沿用原有方式使用 Jest。但若您维护的工具或插件需要导入 Jest 模块,请确保使用包名作为导入路径(将通过 Node 的模块解析机制处理)。
这些变更对任何侵入 Jest 内部实现的情况属于破坏性更新,但对典型的 Jest CLI 和配置使用没有影响。升级后请正常运行测试——若遇到与 Jest 自身模块相关的解析错误,很可能源于需要移除或更新的非受支持导入方式。
通配符模式匹配变更
Jest 的文件模式匹配依赖 (glob) 已升级至 v10 版本。Glob v10 在模式语法和行为上可能存在细微差 异。
值得注意的变化是 glob@10 对大括号扩展和扩展通配符的处理略有不同,并对某些模式要求更严格。若您配置了自定义的 testMatch 模式、moduleNameMapper 模式或其他基于 glob 的配置,多数情况下应仍可工作。但需注意:若发现文件匹配行为与之前不符,可能需要针对新版 glob 引擎调整模式。
升级总结
升级至 Jest 30 时,请首先确保环境满足新版 Node.js 和 TypeScript 要求。针对重命名和移除的选项(特别是 testPathPatterns 和已移除的 --init)更新 Jest 配置文件和 CLI 使用方式。运行测试套件并处理失败用例:
-
替换已移除的匹配器别名,改用官方命名修复相关测试
-
更新因格式化变更(错误原因、空字符串等)导致失败的快照
-
关注 TypeScript 编译错误——它们将引导您更新废弃 API 用法(如
genMockFromModule或已移除类型),并调整因类型检查更严格而需修改的测试
测试愉快!