API 测试指南:从基础到自动化工作流
学习如何有效测试 REST API —— 从使用 HTTP 客户端进行手动测试,到自动化测试套件、状态码和身份验证策略。
API 是软件系统之间的契约。一旦 API 出现故障,所有依赖它的功能都会随之崩溃。然而,API 测试往往被视为事后补救 —— 在部署前临时在浏览器标签页中手动验证一下了事。一套完善的 API 测试策略能够尽早发现缺陷、记录预期行为,并让你信心十足地发布产品。
什么是 API 测试?
API 测试会发送一个 HTTP 请求,并对响应内容进行断言验证:
- 状态码 —— 返回的是
200 OK还是404 Not Found? - 响应体 —— 数据结构是否正确?值是否符合预期?
- 请求头 ——
Content-Type是否设置正确?身份验证头是否存在? - 响应时间 —— 接口是否在可接受的时间范围内响应?
- 错误处理 —— 传入错误输入时会发生什么?是否返回了有意义的错误信息?
必须掌握的 HTTP 状态码
| 状态码 | 含义 | 出现场景 |
|---|---|---|
200 |
OK | 成功的 GET、PUT、PATCH 请求 |
201 |
Created | 成功创建资源的 POST 请求 |
204 |
No Content | 成功的 DELETE 请求或无响应体的操作 |
400 |
Bad Request | 输入无效、JSON 格式错误、缺少字段 |
401 |
Unauthorized | 身份验证令牌缺失或无效 |
403 |
Forbidden | 已认证但无操作权限 |
404 |
Not Found | 资源不存在 |
409 |
Conflict | 资源重复或版本冲突 |
422 |
Unprocessable Entity | JSON 格式合法但存在验证错误 |
429 |
Too Many Requests | 超出请求频率限制 |
500 |
Internal Server Error | 服务端存在 Bug |
503 |
Service Unavailable | 服务器宕机或过载 |
401的意思是"你是谁?" ——403的意思是"我知道你是谁,但你没有权限这样做。"
使用 API Request Builder 进行手动测试
在自动化之前,先手动了解你的接口。我们的 API Request Builder 支持:
- 设置 HTTP 方法(GET、POST、PUT、PATCH、DELETE)
- 添加请求头(Authorization、Content-Type、自定义请求头)
- 无需手动 URL 编码即可构建查询参数
- 使用语法高亮编写 JSON 请求体
- 查看完整响应内容,包括响应头和耗时信息
这非常适合探索新 API、调试特定接口或快速验证修复结果。
测试 REST API:完整的 CRUD 流程
以一个假设的 /users API 为例,完整的测试套件应涵盖以下内容:
创建(POST)
POST /users
Content-Type: application/json
{
"name": "Alice Chen",
"email": "alice@example.com",
"role": "editor"
}
断言:
- 状态码为
201 Created - 响应体包含已创建的用户信息,且带有生成的
id Location请求头指向新资源(如/users/42)
读取(GET)
GET /users/42
Authorization: Bearer <token>
断言:
- 状态码为
200 OK - 响应体与已创建的用户信息一致
id为42
更新(PUT / PATCH)
PATCH /users/42
Content-Type: application/json
{ "role": "admin" }
断言:
- 状态码为
200 OK - 响应中
role字段已更新为"admin" - 其他字段保持不变
删除(DELETE)
DELETE /users/42
Authorization: Bearer <token>
断言:
- 状态码为
204 No Content - 后续发起
GET /users/42返回404
负向测试:大多数人忽略的测试
正向测试验证的是正常路径。负向测试则验证 API 能否优雅地处理错误输入:
- 缺少必填字段 → 返回
400并附带清晰的错误信息 - 数据类型无效(
"age": "twenty")→400 - 资源不存在(
GET /users/99999)→404 - 令牌过期 →
401 - 访问其他用户的数据 →
403 - 发送 10 MB 的请求体 →
413 Payload Too Large - 超出请求频率限制 →
429并附带Retry-After请求头
设计良好的 API 会以可预期、有意义的方式处理失败。
身份验证测试模式
Bearer 令牌(JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
测试场景:
- 有效令牌 → 返回正确响应
- 过期令牌 → 返回
401并附带"Token expired"信息 - 篡改令牌(修改其中一个字符)→
401 - 缺少请求头 →
401 - 使用其他环境的令牌 →
401
在手动测试过程中,可使用我们的 JWT Decoder 来解析令牌并检查过期时间。
API 密钥
X-API-Key: sk_live_abc123
测试:错误的密钥、缺少密钥、权限不足的密钥。
OAuth 2.0 流程
OAuth 会增加复杂性 —— 应将令牌交换接口与资源接口分开单独测试。
验证响应体
不要只检查状态码,还要验证响应的数据结构:
// 使用 Jest + supertest
test("GET /users/:id returns the correct user", async () => {
const response = await request(app).get("/users/42").set("Authorization", `Bearer ${token}`);
expect(response.status).toBe(200);
expect(response.headers["content-type"]).toMatch(/json/);
expect(response.body).toMatchObject({
id: 42,
name: expect.any(String),
email: expect.stringMatching(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
role: expect.oneOf(["admin", "editor", "viewer"]),
});
});
对于结构较复杂的响应,可使用我们的 JSON Schema Validator 进行 JSON Schema 验证 —— 只需定义一次预期结构,即可对所有接口进行校验。
契约测试
在微服务架构中,契约测试用于确保消费方和提供方对 API 的数据结构达成一致。消费方定义所需内容,提供方验证自己是否满足要求。Pact 等工具可以将这一过程自动化。
当不同团队负责不同服务时,契约测试尤为重要 —— 一旦某个字段被重命名或删除,契约测试会在集成之前立即失败,及时暴露问题。
性能与负载测试
功能测试告诉你 API 是否正常工作,性能测试则告诉你它在高负载下表现如何:
- 基准测试 —— 单用户访问时的 p50/p95/p99 响应时间是多少?
- 负载测试 —— 在预期峰值流量下表现如何?
- 压力测试 —— 在什么情况下开始出现故障?
- 峰值测试 —— 流量突然增加 10 倍时会发生什么?
一个常见的目标:在预期峰值负载下,p95 响应时间 < 200ms。
API 测试清单
- 测试每个资源的所有 CRUD 操作
- 测试负向场景:无效输入、缺少身份验证、资源不存在
- 根据 Schema 验证响应体(不仅仅是状态码)
- 测试身份验证边界情况:过期、缺失、篡改的令牌
- 确认错误响应包含有用的提示信息
- 检查分页、过滤和排序功能是否正常
- 测试请求频率限制的行为
- 确认错误响应中不包含敏感数据泄露
- 在预期负载下检查响应时间
优秀的 API 测试既是重构时的安全网,也是最好的文档 —— 它清晰地展示了每个接口的功能以及所期望的输入内容。