JavaScript测试核心是高效可靠:单元测用Jest或Vitest(Vite项目首选),E2E测用Cypress;Jest开箱即用但需注意mock清理、jsdom和假定时器;Cypress适合全流程验证但不支持纯工具函数测试;Vitest更快且兼容Jest语法,适合Vite+ESM项目;CI需缓存、分层设覆盖率阈值并确保单线程运行。

JavaScript 测试不是“要不要做”,而是“怎么高效、可靠地做”。核心判断:单元测试用 Jest,端到端(E2E)测试用 Cypress,两者覆盖绝大多数现代 JS 项目需求;Vitest 是值得认真考虑的 Jest 替代方案,尤其在 Vite 生态中。
为什么 Jest 仍是主流单元测试框架
Jest 内置了断言库、模拟(jest.fn()、jest.mock())、快照测试和覆盖率报告,开箱即用。它对异步代码(async/await、Promise)支持稳定,且与 React/Vue 组件测试集成成熟。
常见踩坑点:
-
beforeEach中未清理jest.clearAllMocks(),导致 mock 状态跨测试污染 - 测试 DOM 时依赖真实浏览器环境,却没配
jsdom(Jest 默认启用,但自定义环境时易漏) - 用
setTimeout或setInterval的逻辑未用jest.useFakeTimers()控制,造成测试超时或不可靠
test('fetchUser 返回用户数据', async () => {
jest.useFakeTimers();
global.fetch = jest.fn().mockResolvedValue({
json: () => Promise.resolve({ id: 1, name: 'Alice' })
});
const user = await fetchUser(1);
expect(user.name).toBe('Alice');
expect(fetch).toHaveBeenCalledWith('/api/users/1');
});
Cypress 适合什么场景?不适合什么
Cypress 是 E2E 测试的事实标准,适用于验证整个应用流程(如登录 → 创建订单 → 支付成功),也常用于组件级交互测试(cy.mount())。它的优势是实时 DOM 观察、自动重试、无需 sleep 或显式等待。
立即学习“Java免费学习笔记(深入)”;
但它不运行在 Node.js 环境,无法直接测试纯工具函数(比如 utils/formatDate());也不支持跨域 iframe 内部操作(如嵌入的第三方支付弹窗)。
关键配置项:
-
cypress.config.ts中的baseUrl必须设为被测服务地址,否则cy.visit()失败 - API 测试需用
cy.intercept()拦截并 stub 响应,而非直接调用fetch - CI 环境下需传
--browser chrome(默认 Electron 不支持部分现代 CSS/JS 特性)
Vitest 比 Jest 快在哪?什么时候该换
Vitest 基于 Vite,利用原生 ES 模块解析和 HMR 能力,启动和文件监听速度明显更快;语法几乎 100% 兼容 Jest(describe、it、expect),迁移成本低。
适用场景:
- 项目已用 Vite 构建,且模块多为 ESM 格式
- 需要高频热重载测试(比如 TDD 开发组件逻辑)
- 想复用 Vite 插件(如
vite-plugin-svgr)或别名(@/components)
注意:vitest 对 CommonJS 模块(如某些老版 npm 包)支持较弱,若测试中 require 报错,需在 vitest.config.ts 中启用 esbuild.target: 'node14' 或改用 deps.inline 强制预构建。
测试命令和 CI 集成的关键细节
本地开发常用命令:
-
npm test→ 运行所有测试(Jest/Vitest 默认) -
npm run test:watch→ 监听变更,只跑相关测试文件(Vitest 的--watch更精准) -
npm run test:ci→ 关闭 watch、启用覆盖率、输出 junit 报告供 CI 解析
CI 中容易忽略的点:
- GitHub Actions 或 GitLab CI 中未缓存
node_modules/.vitest或jest-cache,导致每次冷启动变慢 - 覆盖率阈值(
coverage.thresholds)设为全局 80%,但实际应分层设定(如业务逻辑 ≥90%,工具函数 ≥70%) - 使用
jest --runInBand防止多进程并发写同一覆盖率文件出错,但 Vitest 默认单线程,无需此参数
真正难的不是选框架,而是让测试跑得稳、改得快、看得懂——mock 边界是否清晰、测试命名是否反映行为意图、失败时堆栈能否直指问题根源,这些比框架本身更影响长期可维护性。











