如何为Laravel API编写功能测试? (Pest框架实战)

11次阅读

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

如何为Laravel API编写功能测试? (Pest框架实战)

直接用 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 的 Http Facade,而不是原生 curlguzzlehttp/client 实例
  • Http::assertSent(function (Request $request) { return $request->url()->host() === 'api.stripe.com'; }) 验证是否真的发出了请求

最常被跳过的一步是清空 Sanctum token 数据库状态——连续测试中若不调用 Sanctum::actingAs($user) 或未在 beforeEach() 中重置,token 会复用导致 401 或 419 错误;这个细节不写进 setUp() 就容易在 CI 环境里突然失败。

text=ZqhQzanResources