Flutter WebView Plugin终极指南:5个核心功能解锁移动端混合开发新境界
Jest 30 快速上手:从零安装、编写并运行你的第一个测试
【免费下载链接】jest Delightful JavaScript Testing. 项目地址: https://gitcode.com/gh_mirrors/je/jest
本篇指南以 Jest 30 官方文档《Getting Started》为骨架,带你从零完成 Jest 的安装、第一个测试用例的编写与运行,并延伸覆盖命令行参数、Babel 转译、webpack/Vite/Parcel 打包器协作、TypeScript 与 ESLint 集成等完整上手链路。读完本文,你将掌握一套可直接复制到真实项目中的 Jest 初始化流程,并能对照仓库中的示例与源码理解 expect/toBe 等核心机制的底层行为。文中所有示例在仓库 examples/getting-started 目录下都有完整可运行版本。
一、安装 Jest
使用你习惯的包管理器,将 Jest 安装为项目的开发依赖(devDependencies):
npm install --save-dev jest
或者使用 Yarn:
yarn add --dev jest
安装完成后,Jest 的可执行入口位于 packages/jest/bin/jest.js。从源码可以看到,该入口通过 import-local 优先使用项目本地安装的 Jest(而不是全局版本),随后将控制权交给 jest-cli——这正是"每个项目使用自己版本 Jest"的保障机制,也解释了为什么官方始终推荐以 --save-dev 方式安装,而不是全局安装。
仓库中的完整示例工程 examples/getting-started/package.json 展示了最小依赖组合:在 monorepo 中 jest 与 babel-jest 以 workspace 形式引用,配合 @babel/core、@babel/preset-env 即可运行。
二、编写第一个测试用例
1. 准备被测函数
为假设的"两数相加"函数编写测试。首先创建 sum.js:
function sum(a, b) {
return a + b;
}
module.exports = sum;
2. 编写测试文件
接着创建 sum.test.js,文件名中 .test.js 后缀是 Jest 默认的测试文件匹配模式(testMatch),它会被 Jest 自动发现并执行:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
这段测试做了三件事:require 引入被测模块;用 test() 声明一个名为 "adds 1 + 2 to equal 3" 的测试用例;在断言中用 expect 包装实际值、以 toBe 匹配器断言它严格等于期望值 3。
3. 在 package.json 中添加 npm script
{
"scripts": {
"test": "jest"
}
}
4. 运行并查看输出
执行 yarn test 或 npm test,Jest 会打印如下信息:
PASS ./sum.test.js
✓ adds 1 + 2 to equal 3 (5ms)
PASS 表示测试通过,✓ 及耗时标记了单个用例的结果。至此,你就成功用 Jest 写下了第一个测试。
5. 理解 expect 与 toBe 的底层实现
本测试用到了 expect 与 toBe 两个 API。toBe 的语义是"两个值完全相同",其实现位于 packages/expect/src/matchers.ts 的 matchers 表中(toBe(received, expected),约第 74~104 行),核心逻辑只有一行:
const pass = Object.is(received, expected);
也就是说 toBe 基于 Object.is 判断严格相等,这与 === 基本等价,但能正确处理 NaN === NaN 这类边缘情况。Jest 在失败时还会做额外检查:如果值在"深比较"下相等但引用不同(例如两个内容相同的对象),错误信息中会给出"请改用 toEqual"的提示,这一贴心设计同样来自 matchers.ts 中的 deepEqualityName 逻辑。
如果要比较对象或数组的内容(而非引用),应使用 toEqual,它会在 packages/expect/src/matchers.ts 中通过 equals 与自定义比较器递归检查每个字段;更严格的 toStrictEqual 还会校验 undefined 属性、稀疏数组、类型不匹配等细节。更多匹配器(真值判断、数值比较、字符串、数组、异常抛出等)详见 Using Matchers 与 ExpectAPI.md。
三、从命令行运行 Jest
除了通过 npm script 运行,你还可以直接从命令行调用 jest(前提是它在你的 PATH 中,例如通过 yarn global add jest 或 npm install jest --global 全局安装),并携带各种实用选项。
例如,运行所有文件名匹配 my-test 的测试、使用 config.json 作为配置文件、并在运行结束后弹出原生系统通知:
jest my-test --notify --config=config.json
命令行还有很多常用组合,完整清单见 Jest CLI Options,下面摘录高频用法:
| 命令 | 作用 |
|---|---|
jest | 运行全部测试(默认行为) |
jest my-test 或 jest path/to/my-test.js | 只运行匹配指定模式或文件名的测试 |
jest -o | 只运行与 git/hg 中已变更文件相关的测试 |
jest --findRelatedTests a.js b.js | 运行与 a.js、b.js 相关的测试 |
jest -t name-of-spec | 按 describe/test 中的名称过滤用例 |
jest --watch / jest --watchAll | 进入监听模式(前者默认只跑变更相关测试,后者跑全部) |
需要特别说明的是:
- 通过包管理器运行时,参数直接跟在
npm test --之后即可透传给 Jest,例如npm test -- -u -t="ColorPicker",-u表示更新快照,-t表示按用例名过滤。 - Jest 同时支持驼峰与连字符两种参数写法且效果相同,如
jest --collect-coverage与jest --collectCoverage等价,也可以混合使用。 - CLI.md 开头明确指出:每一个 Configuration 中的配置项都可以通过命令行参数指定,CLI 参数优先级高于配置文件,这是排查"为什么行为与配置不符"时的重要线索。
四、生成基础配置文件
如果不想手动维护配置文件,可以基于项目情况交互式生成:
npm init jest@latest
(Yarn 用户使用 yarn create jest@latest。)运行后 Jest 会询问几个问题,并根据你的项目(模块类型、TypeScript 与否等)生成一份带简短注释的基础配置文件。该功能在仓库中由 packages/create-jest 包实现,生成内容覆盖 testEnvironment、transform 等高频选项,适合作为后续定制配置的起点。
五、使用 Babel 转译现代语法
当项目使用 ES Modules、JSX 或尚未被 Node 原生支持的语法时,需要借助 Babel 让 Jest 能读懂测试代码。
1. 安装依赖
npm install --save-dev babel-jest @babel/core @babel/preset-env
其中 babel-jest 是 Jest 官方的 Babel 桥接包(源码见 packages/babel-jest),它负责调用 Babel 完成代码转换;@babel/preset-env 根据目标环境编译语法。使用 Yarn 时对应 yarn add --dev babel-jest @babel/core @babel/preset-env。
2. 编写 babel.config.js
在项目根目录创建 babel.config.js,让 Babel 针对当前版本的 Node 进行编译:
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
targets: {node: 'current'} 告诉 preset-env 只需兼容当前运行时的 Node 版本,从而只做必要的转译,输出更精简。理想的 Babel 配置取决于你的项目情况(是否用 React、是否发布到浏览器等),建议参考 Babel 官方文档按需裁剪。
3. 让 Babel 配置感知 Jest 环境
Jest 在运行时会做一件重要的事:如果 process.env.NODE_ENV 尚未被设置,它会将其设为 'test'。你的 Babel 配置可以利用这一点,按需启用仅测试阶段需要的编译插件:
module.exports = api => {
const isTest = api.env('test');
// 可以根据 isTest 决定启用哪些 presets 和 plugins
return {
// ...
};
};
api.env('test') 在 Jest 环境下会返回 true(因为它把 NODE_ENV 设为 'test'),从而让你把"测试专用编译"与"生产编译"优雅地区分开。
4. 按需关闭自动转译
需要注意:安装 Jest 时会自动安装 babel-jest,并且只要项目里存在 Babel 配置,babel-jest 就会自动参与文件转换。如果出于某些原因(例如你的代码本就不需要转译)希望关闭这一行为,可以显式清空 transform 配置:
module.exports = {
transform: {},
};
六、与打包器协同工作
大多数场景下,Jest 与各类打包器协作无需特殊配置——唯一的例外是:如果你使用了会"生成文件"或"自定义文件解析规则"的插件/配置,才需要额外处理。
使用 webpack
Jest 可用于以 webpack 管理资源、样式与编译的项目。webpack 相比其他工具会带来一些独特挑战(如 resolve.alias、CSS/静态资源模块、DefinePlugin 注入的全局常量等),这些都需要在 Jest 的 moduleNameMapper、transform 中做镜像配置。完整的 webpack 对接指南请参考 webpack 专项指南。
使用 Vite
Jest 官方不推荐与 Vite 搭配使用,原因是 Jest 与 Vite 的插件系统存在不兼容。虽然有第三方库 vite-jest 提供了集成示例,但该库只兼容不晚于 2.4.2 的 Vite 版本,使用范围受限。一个常用的替代方案是 Vitest——它的 API 与 Jest 兼容,如果项目基于 Vite,可以平滑迁移测试代码。
使用 Parcel
Jest 同样可用于以 parcel-bundler 管理资源、样式与编译的项目,与 webpack 场景类似。Parcel 号称零配置,接入 Jest 时也无需额外配置,直接参考 Parcel 官方文档开始使用即可。
七、在 TypeScript 项目中测试
Jest 本身不解析 TypeScript,需要借助转译工具,共有两条主流路线。
路线一:通过 Babel
前提是已按上文"使用 Babel"一节完成配置。接着安装 TypeScript 预设:
npm install --save-dev @babel/preset-typescript
并将其追加到 babel.config.js 的 presets 列表:
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
],
};
注意此路线的局限:Babel 对 TypeScript 的支持是纯"转译"(strip types),不做类型检查,因此 Jest 运行时不会校验你的类型错误。若需要类型检查,可改用 ts-jest,或在构建流程中单独运行 TypeScript 编译器 tsc 作为补充。
路线二:通过 ts-jest
ts-jest 是带 source map 支持的 TypeScript 预处理器,让 Jest 能直接测试 TypeScript 项目:
npm install --save-dev ts-jest
为了让它生效,通常还需要在 Jest 配置文件(如 jest.config.js)中把 transform 指向 ts-jest,官方安装文档给出了对应的配置片段,例如:
module.exports = {
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
};
类型定义:两种方式
在 TypeScript 测试文件中使用 Jest 全局 API 时,有两种方式获得类型提示:
方式一:官方 @jest/globals(推荐)
Jest 自带的类型定义会随 Jest 版本同步更新。安装:
npm install --save-dev @jest/globals
然后在测试文件中显式导入所需 API:
import {describe, expect, test} from '@jest/globals';
import {sum} from './sum';
describe('sum module', () => {
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
});
@jest/globals 的源码与类型声明位于 packages/jest-globals,它对外暴露 describe、test、expect、jest 等全套 API。其附加用法(如 describe.each/test.each 的 TypeScript 用法、mock 函数的类型标注)可进一步查阅 GlobalAPI.md 与 MockFunctionAPI.md。
方式二:第三方 @types/jest
另一种选择是安装 @types/jest:
npm install --save-dev @types/jest
它提供 Jest 全局变量(test、expect 等)的类型声明,无需手动导入即可使用。注意该包由 DefinitelyTyped 社区维护,属于第三方类型定义,可能存在"版本滞后于最新 Jest 特性"的情况,因此应尽量让 @types/jest 与所用 Jest 版本号对齐,例如使用 Jest 27.4.0 时,安装 27.4.x 的 @types/jest 最为稳妥。
八、与 ESLint 集成
Jest 可以无缝配合 ESLint 使用。前提是:只要在测试文件中使用 Jest 全局辅助函数(describe、it、test、expect 等)之前,先从 @jest/globals 导入它们,ESLint 就不会因为不认识这些全局变量而报 no-undef 错误。
如果不想在每个文件里写导入,可以把 jest 环境注册到 ESLint 配置中,让这些全局变量对所有测试文件可见:
import {defineConfig} from 'eslint/config';
import globals from 'globals';
export default defineConfig([
{
files: ['**/*.js'],
languageOptions: {
globals: {
...globals.jest,
},
},
rules: {
'no-unused-vars': 'warn',
'no-undef': 'warn',
},
},
]);
或者使用社区维护的 eslint-plugin-jest 插件,在 overrides 中针对测试目录开启 jest/globals 环境,效果类似:
{
"overrides": [
{
"files": ["tests/**/*"],
"plugins": ["jest"],
"env": {
"jest/globals": true
}
}
]
}
九、下一步学习路径
从"第一个通过的测试"出发,你可以沿着以下官方文档继续深入:
- Using Matchers:
toBe/toEqual之外的全部内置匹配器,覆盖真值、数值、字符串、数组、对象、异常等断言场景; - Jest CLI Options:完整命令行参数参考(watch、coverage、snapshot、并行度等);
- Configuration:全部配置项详解,与 CLI 参数一一对应;
- GlobalAPI.md 与 MockFunctionAPI.md:全局 API 与 mock 函数的 TypeScript 用法;
- Webpack.md:webpack 项目的完整 Jest 接入指南。
同时,examples/getting-started 目录中的 sum.js、sum.test.js 与 package.json 是本文所有示例的仓库内可运行版本;若想深入 expect/toBe 的实现细节,直接阅读 packages/expect/src/matchers.ts 的 toBe、toEqual、toStrictEqual 定义,即可看清 Object.is、深比较与错误提示增强的完整实现逻辑。
【免费下载链接】jest Delightful JavaScript Testing. 项目地址: https://gitcode.com/gh_mirrors/je/jest
更多推荐
所有评论(0)