全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-15 9 分钟 ✍️ juanwangdev

Node.js 单元测试框架(Mocha/Jest)

Mocha 和 Jest 是 Node.js 主流测试框架,本文对比介绍两者用法。

Jest 测试框架

安装与配置

Bash
npm install --save-dev jest
JSON
// package.json
{
  "scripts": {
    "test": "jest"
  }
}

基本测试

JavaScript
// sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;

// sum.test.js
const sum = require('./sum');

test('1 + 2 = 3', () => {
  expect(sum(1, 2)).toBe(3);
});

describe('sum 函数测试', () => {
  test('正数相加', () => {
    expect(sum(1, 2)).toBe(3);
  });

  test('负数相加', () => {
    expect(sum(-1, -2)).toBe(-3);
  });
});

匹配器

JavaScript
// 相等性
expect(value).toBe(3);           // 严格相等
expect(value).toEqual({ a: 1 }); // 深度相等

// 真值
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();

// 数字
expect(value).toBeGreaterThan(3);
expect(value).toBeLessThan(5);
expect(value).toBeCloseTo(0.3);  // 浮点数

// 字符串
expect(value).toMatch(/hello/);

// 数组
expect(array).toContain(3);
expect(array).toHaveLength(3);

// 异常
expect(() => fn()).toThrow();
expect(() => fn()).toThrow(Error);

异步测试

JavaScript
// Promise
test('异步数据', () => {
  return fetchData().then(data => {
    expect(data).toBe('data');
  });
});

// async/await
test('异步数据', async () => {
  const data = await fetchData();
  expect(data).toBe('data');
});

// resolves/rejects
test('Promise 解析', () => {
  return expect(fetchData()).resolves.toBe('data');
});

test('Promise 拒绝', () => {
  return expect(fetchError()).rejects.toThrow();
});

钩子函数

JavaScript
describe('数据库测试', () => {
  beforeAll(() => {
    // 所有测试前执行一次
  });

  afterAll(() => {
    // 所有测试后执行一次
  });

  beforeEach(() => {
    // 每个测试前执行
  });

  afterEach(() => {
    // 每个测试后执行
  });

  test('测试1', () => {});
  test('测试2', () => {});
});

Mock 函数

JavaScript
// 创建 mock 函数
const mockFn = jest.fn();

// 使用
mockFn('hello');
mockFn('world');

// 断言
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith('hello');

// 设置返回值
mockFn.mockReturnValue(10);
mockFn.mockReturnValueOnce(5);

// 模拟模块
jest.mock('./api');
const api = require('./api');
api.getData.mockResolvedValue({ id: 1 });

Mocha 测试框架

安装与配置

Bash
npm install --save-dev mocha chai
JSON
// package.json
{
  "scripts": {
    "test": "mocha 'test/**/*.js'"
  }
}

基本测试

JavaScript
const { expect } = require('chai');
const sum = require('../sum');

describe('sum 函数测试', () => {
  it('正数相加', () => {
    expect(sum(1, 2)).to.equal(3);
  });

  it('负数相加', () => {
    expect(sum(-1, -2)).to.equal(-3);
  });
});

Chai 断言风格

JavaScript
const { expect, assert } = require('chai');

// BDD 风格(推荐)
expect(value).to.equal(10);
expect(value).to.be.a('number');
expect(array).to.include(3);
expect(fn).to.throw(Error);

// TDD 风格
assert.equal(value, 10);
assert.typeOf(value, 'number');
assert.include(array, 3);

异步测试

JavaScript
// 回调方式
it('异步测试', (done) => {
  fetchData((data) => {
    expect(data).to.equal('data');
    done();
  });
});

// Promise
it('异步测试', () => {
  return fetchData().then(data => {
    expect(data).to.equal('data');
  });
});

// async/await
it('异步测试', async () => {
  const data = await fetchData();
  expect(data).to.equal('data');
});

钩子函数

JavaScript
describe('测试套件', () => {
  before(() => { /* 所有测试前 */ });
  after(() => { /* 所有测试后 */ });
  beforeEach(() => { /* 每个测试前 */ });
  afterEach(() => { /* 每个测试后 */ });

  it('测试用例', () => {});
});

Jest vs Mocha 对比

特性JestMocha
配置零配置需配置
断言库内置需安装 chai
Mock内置需安装 sinon
快照测试支持不支持
并行测试支持需配置
灵活性中等
学习曲线简单中等

注意事项

  • Jest 适合新项目,开箱即用
  • Mocha 灵活,适合复杂需求
  • 测试文件命名:*.test.js*.spec.js
  • 测试覆盖率:jest --coverage

要点总结

  • Jest 零配置、内置断言和 Mock
  • test/it 定义测试用例,expect 断言结果
  • beforeAll/afterAll 管理测试生命周期
  • Mocha 需配合 Chai(断言)和 Sinon(Mock)
  • jest.mock() 模拟依赖模块

📝 发现内容有误?点击此处直接编辑

← 上一篇 使用 Chrome DevTools 调试 Node.js
下一篇 → Node.js 性能分析工具(Clinic.js)
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库