Developer Tools

API 测试指南:从基础到自动化工作流

学习如何有效测试 REST API —— 从使用 HTTP 客户端进行手动测试,到自动化测试套件、状态码和身份验证策略。

8分钟阅读

开发者在屏幕上查看 API 文档

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
  • 响应体与已创建的用户信息一致
  • id42

更新(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 测试既是重构时的安全网,也是最好的文档 —— 它清晰地展示了每个接口的功能以及所期望的输入内容。