用 Pest 写 Laravel API 测试需显式处理 Sanctum 认证(actingAs 或手动加 Bearer Header)、用 assertJsonStructure 校验响应结构、Http::fake() 模拟外部请求,并在 beforeEach 中重置 Sanctum 状态防 token 复用导致 401/419。

直接用 Pest 写 Laravel API 功能测试,比 PHPUnit 更轻、更直观,但容易卡在「请求发不出去」或「响应断言失败却不知原因」上。
如何发起带认证的 API 请求
Pest 默认不自动处理 Laravel 的 API 认证中间件(如 auth:sanctum),直接 $this->getJson('/api/user') 会返回 401。必须显式登录用户并传递 token。
- 用
actingAs($user, 'sanctum')模拟已登录用户(Laravel 9+ Sanctum 场景) - 若用 Token-based 认证(如
api_token字段),需手动加 Header:withHeader('Authorization', 'Bearer '.$token) - 注意:每次测试前调用
Sanctum::actingAs($user)才能触发 token 生成,否则actingAs不生效
如何正确断言 JSON 响应结构
别直接用 ->assertJson(['name' => 'John']),它只做浅层匹配且忽略字段顺序和多余键;API 返回嵌套结构或分页数据时极易误判。
- 对完整结构校验,用
assertJsonStructure()明确字段层级,例如:->assertJsonStructure([ 'data' => ['id', 'name', 'email'], 'meta' => ['per_page'] ]) - 需要精确值比对又含动态字段(如
created_at),先用json_decode($response->getContent(), true)提取再用 PHP 断言 -
assertJsonMissing()比assertJsonMissingExact()更安全——前者忽略缺失字段的嵌套路径,后者要求完全一致
如何模拟第三方 HTTP 调用(如 Stripe 或 Slack webhook)
真实调用外部服务会让测试变慢、不可靠,还可能触发副作用(如发短信、扣款)。Pest + Laravel 的 Http::fake() 是标准解法。
- 在测试开头调用
Http::fake([ 'api.stripe.com/*' => Http::response(['id' => 'pi_123'], 200) ]) - 确保被测代码中使用的是 Laravel 的
HttpFacade,而不是原生cURL或guzzlehttp/client实例 - 用
Http::assertSent(function (Request $request) { return $request->url()->host() === 'api.stripe.com'; })验证是否真的发出了请求
最常被跳过的一步是清空 Sanctum token 数据库状态——连续测试中若不调用 Sanctum::actingAs($user) 或未在 beforeEach() 中重置,token 会复用导致 401 或 419 错误;这个细节不写进 setUp() 就容易在 CI 环境里突然失败。









