laravel测试跑起来只需三步:写测试类、继承tests\testcase、运行php artisan test;卡点几乎全是环境配置和上下文缺失,如csrf未禁用、app_key缺失、db_connection未设为:memory:、refreshdatabase未启用。

直接写测试类、继承 Tests\TestCase、用 php artisan test 运行——这三步走通了,测试就算跑起来了;卡住的几乎全是环境配置和上下文缺失问题,不是语法不会写。
为什么 $this->postJson() 一跑就 500 或 419
这不是你路由或控制器写错了,而是 Laravel 测试环境默认禁用 CSRF 验证,但某些配置会把它“意外打开”。
- 检查
app/Http/Kernel.php中web或api中间件组是否误加了VerifyCsrfToken;Laravel 默认已通过WithoutMiddlewaretrait 关闭它,加了就冲突 -
phpunit.xml里必须有<env name="APP_ENV" value="testing"></env>,否则.env不加载,APP_KEY缺失会导致加密失败,直接 500 - 数据库表不存在也会 500:确认
RefreshDatabasetrait 已启用(tests/TestCase.php默认配好),且phpunit.xml中DB_CONNECTION=sqlite、DB_DATABASE=:memory: - 别在测试里手动调
Artisan::call('migrate')——RefreshDatabase会自动处理,重复执行反而可能报错
actingAs() 不生效,auth()->user() 是 null
根本原因不是模型或 guard 配置错,而是测试没挂上 Laravel 的应用上下文。
- 确保测试类继承自
Tests\TestCase,而不是裸写的PHPUnit\Framework\TestCase - 检查
tests/Pest.php(如果用了 Pest)或测试类顶部是否有uses(Tests\TestCase::class);没有这句,服务容器、事件监听器、软删除 trait 全部不注册 - API 场景下记得传 guard 名:比如
$this->actingAs($user, 'api'),否则默认走webguard,token 可能不匹配 - 若用
Sanctum,需额外调$user->createToken('test')并在请求头带Authorization: Bearer xxx
assertDatabaseMissing() 失败,但数据明明删了
说明事务没生效,或者断言时机不对——Laravel 的数据库断言依赖事务隔离,不是“查库”那么简单。
- 确认测试类显式
use RefreshDatabase或DatabaseTransactions;仅靠TestCase基类不够,事务机制要手动激活 -
assertDatabaseMissing('users', ['id' => 1])必须在请求完成、事务提交后调用;如果在$response->assertStatus(200)前就断言,可能还在事务中,查不到“已删”状态 - 别在测试里用
DB::table('users')->delete()清库——它绕过 Eloquent 事件和软删除逻辑,和你生产代码行为不一致 - 如果用
factory(User::class)->create(),记得用User::factory()->count(3)->create()批量创建,避免单条插入慢影响 CI
Http::fake() 拦不住请求,还是发出去了
Http::fake() 只拦截通过 Laravel Http facade 发出的请求,对 file_get_contents、new GuzzleHttp\Client()、Stripe SDK 等完全无效。
- 先确认被测代码真正在用
Http::get()或Http::post();如果用了第三方 SDK,得换方案:比如对 Guzzle,mock 它的HandlerStack,而不是指望Http::fake() - 通配符路径要写全,例如
Http::fake(['https://api.example.com/v1/*' => Http::response([])]);只写api.example.com或漏掉https://会导致匹配失败 - 如果伪造多个域名,每个都要单独列出来,
Http::fake()不支持正则,也不支持模糊前缀匹配 - 调试时可临时加
Http::preventStrayRequests(),它会让未被 fake 的请求直接抛异常,立刻暴露漏网请求
最常被忽略的是:所有 HTTP 测试都必须走完整中间件生命周期,不能跳过路由解析、CSRF、模型绑定这些环节——否则你测的根本不是用户真实访问路径。环境变量、数据库连接、认证上下文,三者缺一不可。











