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.fn()、jest.mock())、快照测试和覆盖率报告,开箱即用。它对异步代码(async/await、Promise)支持稳定,且与 React/Vue 组件测试集成成熟。
常见踩坑点:
beforeEach 中未清理 jest.clearAllMocks(),导致 mock 状态跨测试污染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 是 E2E 测试的事实标准,适用于验证整个应用流程(如登录 → 创建订单 → 支付成功),也常用于组件级交互测试(cy.mount())。它的优势是实时 DOM 观察、自动重试、无需 sleep 或显式等待。
但它不运行在 Node.js 环境,无法直接测试纯工具函数(比如 utils/formatDate());也不支持跨域 iframe 内部操作(如嵌入的第三方支付弹窗)。
关键配置项:
cypress.config.ts 中的 baseUrl 必须设为被测服务地址,否则 cy.visit() 失败cy.intercept() 拦截并 stub 响应,而非直接调用 fetch
--browser chrome(默认 Electron 不支持部分现代 CSS/JS 特性)Vitest 基于 Vite,利用原生 ES 模块解析和 HMR 能力,启动和文件监听速度明显更快;语法几乎 100% 兼容 Jest(describe、it、expect),迁移成本低。
适用场景:
vite-plugin-svgr)或别名(@/components)注意:vitest 对 CommonJS 模块(如某些老版 npm 包)支持较弱,若测试中 require 报错,需在 vitest.config.ts 中启用 esbuild.target: 'node14' 或改用 deps.inline 强制预构建。
本地开发常用命令:
npm test → 运行所有测试(Jest/Vitest 默认)npm run test:watch → 监听变更,只跑相关测试文件(Vitest 的 --watch 更精准)npm run test:ci → 关闭 watch、启用覆盖率、输出 junit 报告供 CI 解析CI 中容易忽略的点:
node_modules/.vitest 或 jest-cache,导致每次冷启动变慢coverage.thresholds)设为全局 80%,但实际应分层设定(如业务逻辑 ≥90%,工具函数 ≥70%)jest --runInBand 防止多进程并发写同一覆盖率文件出错,但 Vitest 默认单线程,无需此参数真正难的不是选框架,而是让测试跑得稳、改得快、看得懂——mock 边界是否清晰、测试命名是否反映行为意图、失败时堆栈能否直指问题根源,这些比框架本身更影响长期可维护性。