JavaScript 测试:从入门到精通的单元测试、集成测试与端到端测试

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JavaScript 测试:Unit、Integration、E2E — 从入门到精通



现代 Web 应用程序(尤其是基于 Node.js 的)开发离不开高质量的测试。测试不仅能在代码进入生产环境前捕获错误,还能作为活文档,并让你在重构代码时无需担心破坏功能。本文将解析测试金字塔的三个主要层级:unit(单元测试)、integration(集成测试)和 e2e(端到端测试)。你将了解它们的区别、使用哪些工具,并看到基于 Node.js 的完整示例。



1. 单元测试:测试隔离的模块



单元测试是测试金字塔的基础。它们检查单个函数、类或组件在完全隔离外部依赖(数据库、API、文件系统)的情况下的工作状态。主要目标是确保模块逻辑在任何输入数据下都能正确运行。



对于 Node.js,最流行的框架是 Jest(来自 Facebook)。它无需复杂配置,内置断言、模拟和代码覆盖率功能。



示例:测试数组排序函数



// utils.jsfunction sortNumbers(arr) {  if (!Array.isArray(arr)) {    throw new Error('Input must be an array');  }  return [...arr].sort((a, b) => a - b);}

module.exports = { sortNumbers };


// utils.test.jsconst { sortNumbers } = require('./utils');

describe('sortNumbers', () => { test('should sort an array of numbers in ascending order', () => { expect(sortNumbers([3, 1, 2])).toEqual([1, 2, 3]); });

test('should handle an empty array', () => { expect(sortNumbers([])).toEqual([]); });

test('should throw error for non-array input', () => { expect(() => sortNumbers('string')).toThrow('Input must be an array'); });});


单元测试最佳实践:

  • 一个测试只做一项检查(一个断言)。
  • 使用 describe 按函数对测试进行分组。
  • 模拟外部依赖(使用 jest.mock())。
  • 在编写代码之前编写测试(TDD — 测试驱动开发)。


2. 集成测试:检查组件间的交互



集成测试检查系统中不同模块如何协同工作。例如,你的控制器如何与数据库或外部 API 交互。与单元测试不同,这里我们不会模拟所有内容,而是使用真实(或测试)环境。



对于测试基于 Express 的 HTTP 服务器,Supertest 库与 Jest 配合使用效果极佳。



示例:测试 REST 端点



// app.jsconst express = require('express');const app = express();

app.get('/api/hello', (req, res) => { res.json({ message: 'Hello, World!' });});

app.post('/api/data', (req, res) => { const { name } = req.body; if (!name) { return res.status(400).json({ error: 'Name is required' }); } res.status(201).json({ received: name });});

module.exports = app;


// app.test.jsconst request = require('supertest');const app = require('./app');

describe('Integration tests for API', () => { test('GET /api/hello should return a greeting', async () => { const response = await request(app) .get('/api/hello') .expect(200);

expect(response.body).toEqual({ message: 'Hello, World!' }); });

test('POST /api/data with valid body should return 201', async () => { const response = await request(app) .post('/api/data') .send({ name: 'Alice' }) .expect(201);

expect(response.body).toEqual({ received: 'Alice' }); });

test('POST /api/data without name should return 400', async () => {

博客

书籍推荐