jest 是一个开箱即用的全能测试框架,集成了运行器、断言库和模拟功能,特别适合 React 生态。mocha 是一个灵活的测试运行器,本身不含断言库,常与 chai 搭配使用,适合高度定制化的 Node.js 项目。chai 是纯粹的断言库,提供多种断言风格,需配合运行器使用。jasmine 是老牌的全能测试框架,无需配置即可运行,但在现代前端生态中逐渐被 jest 取代,仍常用于 Angular 或 legacy 项目。
在 JavaScript 生态中,测试工具的选择直接影响开发效率和代码质量。jest、mocha、jasmine 和 chai 是最常见的四个名字,但它们的定位完全不同。jest 和 jasmine 是全能型框架,mocha 是运行器,而 chai 只是断言库。让我们从架构角度深入对比它们在实际工程中的表现。
jest 采用“开箱即用”策略,内置了测试运行器、断言库、mock 功能和代码覆盖率工具。
// jest: 所有功能内置
// __tests__/sum.test.js
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
mocha 只是一个测试运行器,负责执行测试用例,但不包含断言或模拟功能。
chai(断言)和 sinon(模拟)等库使用。// mocha + chai: 模块化组合
// test/sum.test.js
const { expect } = require('chai');
describe('Sum Function', function() {
it('adds 1 + 2 to equal 3', function() {
expect(sum(1, 2)).to.equal(3);
});
});
jasmine 也是全能框架,类似 jest 的前身,内置断言和运行器。
jest。// jasmine: 内置断言
// spec/sum.spec.js
describe('Sum Function', function() {
it('adds 1 + 2 to equal 3', function() {
expect(sum(1, 2)).toEqual(3);
});
});
chai 仅提供断言功能,无法独立运行测试。
mocha、jest 或其他运行器。assert、expect、should 三种风格。// chai: 仅断言
const { expect, assert } = require('chai');
expect(value).to.be.true;
assert.equal(value, 1);
value.should.be.true; // 需要启用 should 风格
不同的断言库提供了不同的语法风格,这会影响测试代码的可读性。
jest 使用简洁的 expect 语法,匹配器丰富。
.toBe(), .toEqual(), .toMatchObject() 等。// jest: 丰富的匹配器
expect(user).toMatchObject({ name: 'Alice' });
expect(items).toHaveLength(3);
chai 提供三种风格,最独特的是链式自然语言风格。
expect: 函数式。should: 属性式(需修改原型)。assert: 传统断言式。// chai: 三种风格
expect(color).to.be.red;
color.should.be.red;
assert.equal(color, 'red');
jasmine 使用类似 jest 的 expect,但匹配器较少。
jest 高度相似,迁移成本低。// jasmine: 基础匹配器
expect(color).toEqual('red');
expect(items).toHaveSize(3);
mocha 本身无断言,完全依赖搭配的库(如 chai)。
// mocha: 依赖 chai 断言
// 见上方 Mocha 示例
Mocking 是单元测试的核心,不同工具的处理方式差异巨大。
jest 拥有最强大的内置 Mock 系统。
jest.fn(), jest.mock(),自动模拟模块。// jest: 内置 Mock
const mockFn = jest.fn();
mockFn('arg');
expect(mockFn).toHaveBeenCalledWith('arg');
jest.mock('../axios');
jasmine 内置 spyOn,功能基础但够用。
// jasmine: 内置 Spy
spyOn(obj, 'method').and.returnValue(true);
expect(obj.method).toHaveBeenCalled();
chai 不包含 Mock 功能。
sinon 使用。// chai + sinon: 外部 Mock
const sinon = require('sinon');
const stub = sinon.stub(obj, 'method');
mocha 不包含 Mock 功能。
sinon 或 testdouble。// mocha + sinon: 外部 Mock
// 见上方 Chai 示例,通常一起使用
快照测试(Snapshot Testing)用于防止 UI 或结构意外变更。
jest 原生支持快照测试,是其杀手锏功能。
// jest: 原生快照
expect(component.toJSON()).toMatchSnapshot();
jasmine 不原生支持快照。
jasmine-snapshot 等插件。jest 流畅。// jasmine: 需插件
// expect(component).toMatchSnapshot(); // 非内置
mocha 不原生支持快照。
chai-snapshot 或类似库。// mocha: 需插件
// expect(component).to.matchSnapshot();
chai 无快照功能。
// chai: 不支持
// 无相关 API
jest 强调零配置,但允许通过 jest.config.js 覆盖。
testing-library)。// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
coverageThreshold: { global: { branches: 80 } }
};
mocha 需要手动配置运行参数。
.mocharc.js 或命令行参数控制。// .mocharc.js
module.exports = {
timeout: 5000,
reporter: 'spec',
require: ['@babel/register']
};
jasmine 通过 jasmine.json 配置。
// jasmine.json
{
"spec_dir": "spec",
"spec_files": ["**/*[sS]pec.js"]
}
chai 无需配置,直接引入使用。
chai-http)。// chai 插件
const chaiHttp = require('chai-http');
chai.use(chaiHttp);
尽管架构不同,这些工具在核心测试理念上是一致的。
describe/it (BDD) 或 suite/test (TDD) 结构。// 通用 BDD 结构
describe('User Module', () => {
it('should create a user', () => {
// 测试逻辑
});
});
async/await 或 done 回调处理异步代码。// 通用异步测试
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
beforeEach, afterEach, before, after 等生命周期钩子。// 通用 Hooks
beforeEach(() => {
// 重置状态
});
| 特性 | jest | mocha | jasmine | chai |
|---|---|---|---|---|
| 类型 | 全能框架 | 测试运行器 | 全能框架 | 断言库 |
| 断言库 | 内置 | 需搭配 (如 Chai) | 内置 | 本身就是 |
| Mock 功能 | 强大内置 | 需搭配 (如 Sinon) | 基础内置 | 无 |
| 快照测试 | ✅ 原生支持 | ❌ 需插件 | ❌ 需插件 | ❌ 不支持 |
| 配置复杂度 | 低 (零配置) | 高 (手动配置) | 低 | 无 |
| 适用场景 | React/前端 | Node.js/定制 | Angular/遗留 | 配合 Mocha |
jest 是现代前端开发的首选 🏆。它的集成度高、生态丰富,特别是快照测试和 mocking 功能,能极大提升开发效率。如果你在使用 React、Vue 或现代构建工具,jest 是最稳妥的选择。
mocha + chai 适合需要精细控制的场景 🛠️。如果你在编写 Node.js 后端服务,或者需要特殊的测试报告、复杂的异步流程控制,这种模块化组合提供了最大的灵活性。
jasmine 适合维护旧项目或简单脚本 📜。如果没有历史包袱,新项目中不建议优先使用,因为它的生态活跃度不如 jest。
chai 永远不要单独使用 🔗。它是 mocha 的最佳搭档,或者在 jest 无法满足特定断言需求时作为补充。
核心原则:测试工具的目的是保障代码质量,而不是增加负担。选择那个能让你的团队最快写出可靠测试的工具 — 对于大多数前端团队,这通常是 jest。
选择 chai 如果你已经使用了 mocha 或其他运行器,但需要更丰富的断言语法(如 should 风格)。它不适合作为独立的测试工具,而是作为断言层的补充。
选择 jest 如果你的项目基于 React 或需要开箱即用的体验。它内置了快照测试、强大的 mocking 功能和并行执行能力,适合大多数现代前端项目,能显著减少配置时间。
选择 mocha 如果你需要极高的配置灵活性,或者是在 Node.js 后端环境中工作。它允许你自由组合断言库(如 chai)和模拟库,适合需要精细控制测试流程的复杂架构。
选择 jasmine 如果你维护的是旧版 Angular 项目,或者需要一个无需安装额外依赖即可运行的轻量级 BDD 框架。在新项目中,除非有特定遗留要求,否则通常建议优先考虑 jest。
Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.
For more information or to download plugins, view the documentation.
Chai is an assertion library, similar to Node's built-in assert. It makes testing much easier by giving you lots of assertions you can run against your code.
chai is available on npm. To install it, type:
$ npm install --save-dev chai
You can also use it within the browser; install via npm and use the index.js file found within the download. For example:
<script src="./node_modules/chai/index.js" type="module"></script>
Import the library in your code, and then pick one of the styles you'd like to use - either assert, expect or should:
import { assert } from 'chai'; // Using Assert style
import { expect } from 'chai'; // Using Expect style
import { should } from 'chai'; // Using Should style
import 'chai/register-assert'; // Using Assert style
import 'chai/register-expect'; // Using Expect style
import 'chai/register-should'; // Using Should style
import { assert } from 'chai'; // Using Assert style
import { expect } from 'chai'; // Using Expect style
import { should } from 'chai'; // Using Should style
should(); // Modifies `Object.prototype`
import { expect, use } from 'chai'; // Creates local variables `expect` and `use`; useful for plugin use
mocha spec.js --require chai/register-assert.js # Using Assert style
mocha spec.js --require chai/register-expect.js # Using Expect style
mocha spec.js --require chai/register-should.js # Using Should style
Read more about these styles in our docs.
Chai offers a robust Plugin architecture for extending Chai's assertions and interfaces.
chai-pluginbrowser if your plugin works in the browser as well as Node.jsbrowser-only if your plugin does not work with Node.jsError constructor thrown upon an assertion failing.Thank you very much for considering to contribute!
Please make sure you follow our Code Of Conduct and we also strongly recommend reading our Contributing Guide.
Here are a few issues other contributors frequently ran into when opening pull requests:
chai.js build. We do it once per release.Please see the full Contributors Graph for our list of contributors.
Feel free to reach out to any of the core contributors with your questions or concerns. We will do our best to respond in a timely manner.
This project would not be what it is without the contributions from our prior core contributors, for whom we are forever grateful: