1. 测试金字塔
/
/ E2E 测试 ← 少而精,覆盖核心用户路径
/_________________/
/ 集成测试 ← 测试模块间交互
/_________________/
/ 单元测试 ← 大量、快速、独立
/_________________/
| 类型 | 比例 | 速度 | 工具 |
|---|---|---|---|
| 单元测试 | 70% | < 100ms | Jest、Vitest |
| 集成测试 | 20% | < 1s | Supertest + Test DB |
| E2E 测试 | 10% | < 10s | Playwright、Cypress |
2. 单元测试(Jest)
// utils.test.js
const { sum, asyncFetch } = require('./utils');
describe('utils', () => {
beforeEach(() => {
// 每个测试前执行
});
test('sum adds numbers', () => {
expect(sum(1, 2)).toBe(3);
expect(sum(-1, 1)).toBe(0);
});
test('async fetch', async () => {
const data = await asyncFetch('https://api.example.com');
expect(data).toHaveProperty('id');
});
// Mock
test('with mocked dependency', () => {
const mockFn = jest.fn().mockReturnValue('mocked');
expect(mockFn()).toBe('mocked');
expect(mockFn).toHaveBeenCalledTimes(1);
});
});
// 覆盖率
// npx jest --coverage
3. 集成测试
// app.test.js
const request = require('supertest');
const app = require('./app');
describe('API Integration', () => {
beforeAll(async () => {
await setupTestDatabase();
});
afterAll(async () => {
await teardownTestDatabase();
});
test('GET /users returns users', async () => {
const res = await request(app).get('/users');
expect(res.status).toBe(200);
expect(res.body).toBeInstanceOf(Array);
});
test('POST /users creates user', async () => {
const res = await request(app)
.post('/users')
.send({ email: 'test@example.com', name: 'Test' });
expect(res.status).toBe(201);
expect(res.body.email).toBe('test@example.com');
});
});
4. 微服务通信
4.1 gRPC
// user.proto
syntax = "proto3";
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc ListUsers (ListUsersRequest) returns (stream User);
}
message GetUserRequest { string id = 1; }
message User { string id = 1; string name = 2; string email = 3; }
// gRPC 客户端
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDef = protoLoader.loadSync('user.proto');
const grpcObject = grpc.loadPackageDefinition(packageDef);
const client = new grpcObject.UserService('localhost:50051', grpc.credentials.createInsecure());
client.getUser({ id: '123' }, (err, response) => {
console.log(response);
});
4.2 消息队列(RabbitMQ)
const amqp = require('amqplib');
// 生产者
const conn = await amqp.connect('amqp://localhost');
const ch = await conn.createChannel();
await ch.assertQueue('orders');
ch.sendToQueue('orders', Buffer.from(JSON.stringify({ orderId: '123' })));
// 消费者
await ch.consume('orders', (msg) => {
const order = JSON.parse(msg.content.toString());
processOrder(order);
ch.ack(msg);
});
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。