jasmine、jest、mocha 和 qunit 都是用于 JavaScript 应用的测试框架,支持单元测试、集成测试等场景。它们都提供断言、测试组织、异步支持等核心能力,但设计理念、默认配置和生态系统差异显著。jasmine 是行为驱动开发(BDD)风格的独立测试框架;jest 由 Facebook 维护,强调零配置、快照测试和内置模拟;mocha 以高度可扩展性和灵活性著称,常与 Chai、Sinon 等库组合使用;qunit 最初为 jQuery 开发,适合 DOM 操作和浏览器环境测试,语法简洁直接。
在现代前端开发中,选择合适的测试框架直接影响开发效率、测试覆盖率和长期维护成本。jasmine、jest、mocha 和 qunit 虽同属 JavaScript 测试工具,但各自的设计哲学和适用场景大不相同。本文从真实工程角度出发,通过代码示例和关键特性对比,帮助你做出明智选择。
不同框架对测试用例的组织方式直接影响代码可读性。
jasmine 采用经典的 BDD 风格,使用 describe/it/expect,所有功能内置。
// jasmine
describe('Calculator', () => {
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
it('spies on function calls', () => {
const spy = jasmine.createSpy('add');
spy(1, 2);
expect(spy).toHaveBeenCalledWith(1, 2);
});
});
jest 语法与 jasmine 高度相似(因早期 fork 自 jasmine),但扩展了更多功能,如 test 别名。
// jest
test('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
describe('async operations', () => {
it('fetches user data', async () => {
const user = await fetchUser();
expect(user.name).toBe('Alice');
});
});
mocha 本身只提供测试结构(describe/it),断言需搭配其他库(如 Chai)。
// mocha + chai
const { expect } = require('chai');
describe('Calculator', () => {
it('adds two numbers', () => {
expect(add(1, 2)).to.equal(3);
});
});
qunit 使用更传统的 QUnit.test,风格接近 xUnit,适合习惯 TDD 的开发者。
// qunit
QUnit.test('adds two numbers', assert => {
assert.equal(add(1, 2), 3);
});
QUnit.module('Async tests', () => {
QUnit.test('fetches user', async assert => {
const user = await fetchUser();
assert.equal(user.name, 'Alice');
});
});
现代应用大量依赖异步操作,各框架处理方式如下:
jasmine 支持 done 回调、async/await 和 Promise。
// jasmine async
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeTruthy();
});
it('uses done callback', (done) => {
fetchData().then(data => {
expect(data).toBeTruthy();
done();
});
});
jest 原生支持 async/await,并提供 waitFor 等工具用于测试异步 UI。
// jest async
test('fetches data', async () => {
const data = await fetchData();
expect(data).toBeTruthy();
});
mocha 同样支持 async/await、done 和返回 Promise。
// mocha async
it('fetches data', async () => {
const data = await fetchData();
expect(data).to.exist;
});
qunit 通过 assert.async() 或 async/await 处理异步。
// qunit async
QUnit.test('fetches data', async assert => {
const data = await fetchData();
assert.ok(data);
});
QUnit.test('uses async callback', assert => {
const done = assert.async();
fetchData().then(data => {
assert.ok(data);
done();
});
});
jasmine 内置丰富的 matcher(如 toBe, toEqual, toHaveBeenCalled)和 spy 功能。
// jasmine spy
const obj = { method: () => {} };
spyOn(obj, 'method');
obj.method();
expect(obj.method).toHaveBeenCalled();
jest 提供更强大的 mock 系统,包括自动 mock 模块、jest.fn() 和 jest.mock()。
// jest mock
jest.mock('./api');
const mockApi = require('./api');
mockApi.fetchUser.mockResolvedValue({ name: 'Alice' });
mocha 本身无断言或 mock,需依赖 Chai(断言)和 Sinon(spy/stub)。
// mocha + sinon + chai
const sinon = require('sinon');
const { expect } = require('chai');
const stub = sinon.stub(api, 'fetchUser').resolves({ name: 'Alice' });
expect(await api.fetchUser()).to.deep.equal({ name: 'Alice' });
stub.restore();
qunit 内置基本断言(equal, ok, deepEqual),mock 需手动实现或使用插件。
// qunit basic assertion
QUnit.test('basic check', assert => {
assert.equal(1 + 1, 2);
assert.ok(true);
});
jest 是唯一原生支持快照测试的框架,且内置 Istanbul 集成,一行命令即可生成覆盖率报告。
// jest snapshot
test('component renders correctly', () => {
const tree = renderer.create(<Button />).toJSON();
expect(tree).toMatchSnapshot();
});
// CLI: jest --coverage
jasmine、mocha 和 qunit 均不支持快照测试。覆盖率需借助外部工具(如 nyc + Istanbul):
# mocha + nyc
nyc mocha
# jasmine + nyc
nyc jasmine
# qunit 需通过 Karma 或自定义脚本集成
jasmine:官方提供 jasmine-core(浏览器)和 jasmine-npm(Node.js),两者 API 一致。jest:基于 JSDOM 模拟浏览器环境,原生运行于 Node.js,适合无头测试。mocha:通过 mocha CLI 运行于 Node.js,配合 Karma 可在真实浏览器中执行。qunit:最初为浏览器设计,现也支持 Node.js(qunit CLI),但主要优势仍在浏览器端。jest:零配置启动,但高级定制(如自定义 transformer)需深入文档。mocha:高度可插拔,但需手动集成断言、mock、报告器等,适合有经验的团队。jasmine:配置简单,适合快速开始,但扩展性有限。qunit:配置极简,适合小型项目或传统 Web 应用,现代前端工具链支持较弱。| 场景 | 推荐框架 | 理由 |
|---|---|---|
| React/Vue 项目,需快照测试 | jest | 内置快照、mock、覆盖率,与现代框架无缝集成 |
| 需要灵活组合工具链 | mocha | 可自由选择断言、mock、报告器,适合复杂需求 |
| 轻量级项目,避免依赖 | jasmine | 开箱即用,无额外依赖,BDD 风格清晰 |
| 浏览器 DOM 测试,jQuery 项目 | qunit | 原生浏览器支持,API 简洁,启动迅速 |
jest,尤其使用 React/Vue 时。qunit 或 jasmine 更平滑。mocha 提供最大自由度。无论选择哪个框架,关键是保持测试的可读性、可靠性和运行速度 —— 这才是高质量测试套件的核心。
选择 jest 如果你追求快速上手、完整的内置功能(如快照测试、自动 mock、覆盖率报告)以及与 React/Vue 等现代框架的深度集成。它特别适合大型项目或需要高可靠性的测试套件,但其“魔法”式设计可能在调试或定制时带来一定复杂性。
选择 jasmine 如果你需要一个开箱即用、无需额外依赖的 BDD 风格测试框架,尤其适合轻量级项目或希望避免复杂配置的团队。它内置断言、spy 和异步支持,适合在浏览器和 Node.js 中运行,但生态扩展性不如 mocha 或 jest。
选择 mocha 如果你需要最大程度的灵活性和对测试工具链的精细控制,例如自由搭配断言库(Chai)、mock 工具(Sinon)或报告器。它适合已有技术栈较复杂或对测试流程有特殊需求的项目,但需自行组装生态组件,初始配置成本较高。
选择 qunit 如果你主要进行浏览器端测试,尤其是涉及 DOM 操作、jQuery 插件或需要简单直观 API 的场景。它启动迅速、文档清晰,适合小型项目或传统 Web 应用,但在现代前端工程化(如模块打包、快照测试)方面支持有限。
🃏 Delightful JavaScript Testing
👩🏻💻 Developer Ready: Complete and ready to set-up JavaScript testing solution. Works out of the box for any React project.
🏃🏽 Instant Feedback: Failed tests run first. Fast interactive mode can switch between running all tests or only test files related to changed files.
📸 Snapshot Testing: Jest can capture snapshots of React trees or other serializable values to simplify UI testing.
Read More: https://jestjs.io/