测试前须调通TestCase基类与数据库重置,确保phpunit.xml中DB_CONNECTION=sqlite且DB_DATABASE=:memory:,运行composer dump-autoload,并验证路由注册、认证模拟及断言完整性。

测试前必须调通 TestCase 基类和数据库重置
不跑通基础环境,后续所有测试都会卡在「数据库残留数据」或「应用未启动」上。Laravel 的 TestCase 默认继承自 Illuminate\Foundation\Testing\TestCase,它会在每个测试方法前后重建应用实例并回滚迁移——但前提是你的 phpunit.xml 里配置了正确的 DB_CONNECTION(通常是 sqlite 内存模式)。
常见错误现象:SQLSTATE[HY000]: General error: 1 no such table,说明测试没走内存 SQLite,而是连到了开发库;或者 Target class [App\Http\Controllers\Api\V1\PostsController] does not exist,是自动加载没刷新。
- 确保
phpunit.xml中DB_CONNECTION设为sqlite,且DB_DATABASE设为:memory: - 运行
composer dump-autoload,尤其改过命名空间或控制器路径后 - 首次运行前手动执行
php artisan migrate --database=testing(如果用了独立测试库),或直接依赖内存 SQLite 避免这步
json() 和 getJson() 别混用,路由没注册就报 405
Laravel 测试里发 JSON 请求,不是所有方法都等价。$this->getJson('/api/posts') 是快捷方式,底层自动加 Accept: application/json 和 Content-Type: application/json;而 $this->json('GET', '/api/posts') 更底层,但需要你手动保证路由已定义、中间件已启用(比如 api 中间件组)。
典型翻车场景:写了 $this->json('GET', '/api/posts') 却忘了在 routes/api.php 里注册该路由,结果返回 405 Method Not Allowed —— 实际是 404,但 Laravel 把未匹配路由统一判成 405。
立即学习“PHP免费学习笔记(深入)”;
- 优先用
getJson()/postJson()等语义化方法,少出错 - 若用
json(),务必确认路由存在、HTTP 方法匹配、且没被中间件(如auth:sanctum)拦截 - 测试带认证的接口,必须先调
$this->actingAs($user, 'sanctum'),否则 401 不是“没登录”,是“token 根本没传”
验证响应结构别只看状态码,assertJsonStructure() 很容易漏字段
写断言时,光测 assertStatus(200) 没用。API 返回 JSON,核心是字段是否齐全、嵌套是否正确、类型是否符合预期。Laravel 的 assertJsonStructure() 能校验键名,但它默认不检查缺失字段 —— 比如接口实际返回 { "data": { "id": 1 } },你写 assertJsonStructure(['data' => ['id', 'title']]),测试照样通过,因为 title 字段没出现也不会报错。
更隐蔽的问题:当返回数组列表时,assertJsonStructure(['data' => [['id', 'name']] ]) 只校验第一个元素结构,后面元素字段缺失也检测不到。
- 用
assertJsonMissing()显式排除不该出现的字段(比如敏感字段password_hash) - 对列表响应,用
assertJsonCount(3, 'data')先确认数量,再挑一个索引做深度校验:assertJsonPath('data.0.id', 1) - 复杂嵌套建议拆成多个断言,而不是堆在一个
assertJsonStructure()里
测试文件放错位置会导致 artisan test 找不到
Laravel 默认只扫描 tests/Feature 和 tests/Unit 下的 PHP 文件。如果你把 API 测试随手建在 tests/Api 或 tests/Http 目录下,运行 php artisan test 或 ./vendor/bin/phpunit 都不会执行它——没有报错,只是静默跳过。
另一个坑是文件命名:Laravel 要求测试类名以 Test 结尾(如 PostApiTest.php),且类名必须匹配文件名;如果写成 PostApiTests.php(复数),Composer 自动加载会失败,报 Class "PostApiTests" not found。
- API 测试统一放在
tests/Feature/Api(非必须,但符合直觉) - 文件名必须是
*Test.php,类名必须是*Test,大小写严格一致 - 如果要用自定义目录,在
phpunit.xml的<testsuites>里显式添加<directory>tests/Feature/Api</directory>
最常被忽略的其实是请求头和中间件组合:比如开了 throttle:api,连续跑 5 个测试就可能触发限流,返回 429 却以为是代码逻辑错了。这类问题不会在单测里暴露,得靠真实请求路径去复现。



















