Pest 测试需显式启用 Laravel 测试环境:在 tests/Pest.php 中调用 uses(Tests\TestCase::class)->in('Feature', 'Unit'),并确保 TestCase 使用 CreatesApplication;数据库需配合 RefreshDatabase trait 与 :memory: SQLite;模型工厂改用 User::factory()->create();HTTP 测试依赖正确 bootstrap 路径和路由缓存。

直接用 Pest 写 Laravel 单元测试,比原生 PHPUnit 更轻、更直观,但前提是得绕开几个默认配置陷阱——比如自动加载、Laravel 服务容器绑定、以及测试数据库隔离问题。
为什么 Pest 测试里 app() 返回 null 或报错?
这是最常见的启动失败现象。Pest 默认不自动调用 Laravel 的测试启动逻辑(CreatesApplication trait),导致服务容器未初始化。
- 必须在
tests/Pest.php中显式引入 Laravel 测试辅助函数:uses(Tests\TestCase::class)->in('Feature', 'Unit'); - 确保
Tests\TestCase已继承Illuminate\Foundation\Testing\TestCase,且含use CreatesApplication; - 不要手动调用
require_once 'vendor/autoload.php'—— Pest 自带 autoloader,重复加载会破坏 Laravel 的容器单例
如何让 database() → migrate() 在每个测试前重置干净?
Pest 的 beforeEach 和 Laravel 的 RefreshDatabase trait 必须配合使用,否则迁移只跑一次或完全不跑。
- 在测试文件顶部启用 trait:
uses(RefreshDatabase::class);
- 若用内存 SQLite(推荐单元测试):在
phpunit.xml或phpunit.xml.dist中确认DB_CONNECTION=sqlite且DB_DATABASE=:memory: - 避免在
beforeEach里手动Artisan::call('migrate:fresh')—— 这会绕过RefreshDatabase的事务回滚机制,大幅拖慢速度
测试 Eloquent 模型时,factory()->create() 报 Class not found 怎么办?
Laravel 9+ 已移除全局 factory() 辅助函数,Pest 里仍沿用旧写法容易出错。
- 改用类名调用工厂:
User::factory()->create();
- 确保模型已声明工厂路径(如
UserFactory在database/factories/UserFactory.php),且命名空间匹配 - 如果用 PHP 8.1+,注意
User::factory()返回的是UserFactory实例,不是静态代理 —— 不支持链式调用create()外的自定义方法,除非工厂里显式定义
test('works') -> get('/api/users') -> assertStatus(200) 为什么返回 404?
路由未加载,通常是因为 Pest 测试没走 Laravel 的 HTTP 内核,或中间件干扰了请求生命周期。
- 确保测试类用了
Illuminate\Foundation\Testing\RefreshDatabase和Illuminate\Foundation\Testing\WithFaker(后者非必须,但常配套) - 检查是否启用了
VerifyCsrfToken中间件 —— 测试中默认关闭,但如果在app/Http/Middleware/VerifyCsrfToken.php里写了硬编码排除逻辑,可能意外拦截 - 别用
Route::get()临时注册路由来“凑数”——Pest 的 HTTP 测试依赖真实路由缓存,应运行php artisan config:clear && php artisan route:clear确保缓存更新
最易被忽略的是 phpunit.xml 里的 bootstrap 路径是否指向 vendor/autoload.php 而非 Laravel 的 tests/bootstrap.php —— Pest 需要后者才能加载 Laravel 测试环境。这个配置错一位,整个测试就变成“裸 PHPUnit”,连 app() 都拿不到。










