JavaScript 测试:单元测试、集成测试、端到端测试高级进阶

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

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

开始课程

引言:为什么高级测试是 JavaScript 项目的必备技能

在现代 Node.js 开发中,测试已不再是可选环节。如果没有高质量的代码测试覆盖率,任何重构或添加新功能都可能变成一场“俄罗斯轮盘赌”。然而,仅仅编写几个 assert 语句是不够的。在高级层面,开发者必须掌握三个主要层次:单元测试(验证独立模块)、集成测试(组件、数据库、API 之间的交互)和端到端测试(模拟用户操作)。在本文中,我们将以 Node.js 为例,结合 Jest、Supertest 和 Playwright 等现代工具,深入剖析每个层次的实用技巧。



1. 单元测试:高级隔离、模拟与桩代码

单元测试用于验证单个函数或模块在隔离外部依赖(如数据库、文件系统、网络请求)时的运行情况。关键任务是正确地模拟这些依赖,以确保测试快速且结果确定。



Jest 中的高级模拟技术

考虑一个示例:一个函数会调用外部 API 并将结果缓存到 Redis。我们需要在不执行真实请求的情况下测试缓存逻辑。

// cacheService.jsconst axios = require('axios');const redis = require('redis');

class CacheService { constructor() { this.client = redis.createClient(); }

async fetchData(url) { const cached = await this.client.get(url); if (cached) return JSON.parse(cached);

const response = await axios.get(url); await this.client.setEx(url, 3600, JSON.stringify(response.data)); return response.data; }}

module.exports = CacheService;


// cacheService.test.jsconst CacheService = require('./cacheService');const axios = require('axios');const redis = require('redis');

jest.mock('axios');jest.mock('redis', () => ({ createClient: jest.fn(() => ({ get: jest.fn(), setEx: jest.fn() }))}));

describe('CacheService', () => { let service; let mockRedisClient;

beforeEach(() => { mockRedisClient = redis.createClient(); service = new CacheService(); });

test('should return cached data if present', async () => { const url = 'https://api.example.com/data'; const cachedData = { id: 1, value: 'cached' }; mockRedisClient.get.mockResolvedValue(JSON.stringify(cachedData));

const result = await service.fetchData(url);

expect(result).toEqual(cachedData); expect(axios.get).not.toHaveBeenCalled(); });

test('should fetch and cache data if not cached', async () => { const url = 'https://api.example.com/data'; const apiData = { id: 2, value: 'fresh' }; mockRedisClient.get.mockResolvedValue(null); axios.get.mockResolvedValue({ data: apiData });

const result = await service.fetchData(url);

expect(result).toEqual(apiData); expect(mockRedisClient.setEx).toHaveBeenCalledWith(url, 3600, JSON.stringify(apiData)); });});

关键要点:

  • jest.mock('axios') 会自动模拟整个 axios 模块。
  • 对于 Redis,我们使用一个工厂函数,返回一个包含 get 和 setEx 方法的模拟对象。
  • 我们验证了当缓存存在时,外部调用不会发生。


2. 集成测试:测试与真实数据库和 API 的交互

集成测试用于验证系统不同部分如何协同工作。对于 Node.js,这通常意味着使用真实(或测试)数据库来测试 Express 路由。最佳工具是 Supertest 与 Jest 配合使用。



配置测试数据库和 Supertest

示例:一个用于用户管理的 API。我们使用内存中的 SQLite 来实现隔离

博客

书籍推荐