测试驱动开发遵循红-绿-重构循环:先写失败测试(红),再实现代码通过测试(绿),最后优化代码结构。使用Jest可高效编写单元测试,支持断言、异步测试、模拟和覆盖率分析,提升代码质量与可维护性。

测试驱动开发(TDD)是一种以测试为先导的软件开发方式。在编写实际功能代码之前,先编写单元测试用例,再通过实现代码让测试通过。Jest 是一个由 Facebook 开发的 JavaScript 测试框架,因其简单易用、功能强大,广泛应用于 React 项目和 Node.js 服务中。本文将介绍如何在 TDD 实践中使用 Jest 编写高质量的单元测试。
理解 TDD 的基本流程
TDD 遵循“红-绿-重构”的循环模式:
- 红(Red):先编写一个失败的测试用例,验证期望行为尚未实现
- 绿(Green):编写最简代码使测试通过
- 重构(Refactor):优化代码结构,同时确保测试仍然通过
这种流程有助于保持代码简洁、可维护,并确保每一部分都有对应的测试覆盖。
配置 Jest 环境
在项目根目录初始化 npm 并安装 Jest:
npm init -ynpm install --save-dev jest
在 package.json 中配置测试命令:
"scripts": { "test": "jest", "test:watch": "jest --watch" }如果测试文件使用 ES6 模块语法(import/export),需配置 Babel 或使用 Node.js 原生支持,或改用 .cjs 扩展名。对于大多数现代项目,推荐结合 babel-jest 使用。
编写第一个单元测试
假设我们要实现一个简单的加法函数 sum(a, b)。按照 TDD 步骤,先写测试:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
运行 npm test,测试会失败(红阶段)。接着创建 sum.js 文件并实现函数:
const sum = (a, b) => a + b;
module.exports = sum;
再次运行测试,应显示通过(绿阶段)。此时可以进入重构环节,比如增强参数校验,同时保证测试仍通过。
使用 Jest 的核心断言与匹配器
Jest 提供丰富的 expect 匹配器来验证各种结果:
- toBe(value):严格相等(===)
- toEqual(value):深度比较对象或数组
- toBeDefined():检查值不为 undefined
- toBeTruthy() / toBeFalsy():检查真假值
- toContain(item):检查数组或字符串是否包含某项
- toThrow():验证函数是否抛出异常
例如:
MediPro乡镇政府门户网站系统,适合乡镇政府机构创建地方门户网站,用以宣传本地资源,实现政务公开,促进乡镇基层信息化建设。本系统基于PHP+MYSQL开发,预设了乡镇风采、党政机构、政务公开、投资指南、服务导航、文件下载、公众互动、领导信箱等乡镇政府门户网站常用的栏目和测试数据,采用适合乡镇政府门户网站的专用模版,增强了系统的针对性和易用性。除了文章系统、图文系统、下载系统、社区交流、反馈表单
const data = { one: 1 };
data.two = 2;
expect(data).toEqual({ one: 1, two: 2 });
});
test('throws on invalid input', () => {
expect(() => sum('a', 'b')).toThrow();
});
测试异步代码
Jest 支持 Promise 和 async/await 的测试。例如有一个异步获取用户信息的函数:
// fetchUser.jsconst fetchUser = () =>
Promise.resolve({ id: 1, name: 'John' });
module.exports = fetchUser;
对应的测试写法:
// fetchUser.test.jsconst fetchUser = require('./fetchUser');
test('should resolve user data', async () => {
const user = await fetchUser();
expect(user).toEqual({ id: 1, name: 'John' });
});
也可以使用 resolves 匹配器:
模拟(Mocking)函数与模块
在测试中,常需要隔离外部依赖,如 API 调用、数据库操作等。Jest 提供强大的 mocking 功能。
例如,有一个函数依赖于另一个函数 getPrice():
const getPrice = require('./priceUtils');
const total = (count) => getPrice() * count;
module.exports = total;
测试时可模拟 getPrice 的返回值:
const total = require('./checkout');
const getPrice = require('./priceUtils');
jest.mock('./priceUtils'); // 自动创建 mock
test('calculates total with mocked price', () => {
getPrice.mockReturnValue(10);
expect(total(5)).toBe(50);
});
覆盖率报告
Jest 可生成测试覆盖率报告。添加配置:
"scripts": {"test:coverage": "jest --coverage"
}
运行后会在项目中生成 coverage 目录,打开 index.html 可查看每行代码的覆盖情况。建议设置最低阈值以保证质量:
// jest.config.jsmodule.exports = {
collectCoverageFrom: ['src/**/*.{js,jsx}'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
}
};
基本上就这些。掌握 Jest 的基本用法并坚持 TDD 流程,能显著提升代码质量和开发效率。关键是养成“先写测试”的习惯,逐步构建稳健的应用程序。不复杂但容易忽略。










