在 laravel 中运行首个 pest 测试需先确保 phpunit 环境,执行 composer require --dev pestphp/pest pestphp/pest-plugin-laravel,再运行 php artisan pest:install 生成配置和测试目录,最后用 ./vendor/bin/pest 或 php artisan test 启动。

怎么在 Laravel 里跑起第一个 Pest 测试
Pest 是 Laravel 官方推荐的测试框架,本质是 PHPUnit 的轻量封装,但写法更简洁。它不是独立安装的“新东西”,而是基于 PHPUnit 构建的 DSL 层——所以你得先有 PHPUnit 环境,再装 Pest。
- 用
composer require --dev pestphp/pest pestphp/pest-plugin-laravel安装(注意:Laravel 10+ 默认已预装pest命令,但插件仍需手动加) - 运行
php artisan pest:install生成配置和基础测试目录(会创建tests/Pest.php和tests/Feature/tests/Unit) - 别直接删掉
tests/TestCase.php——Pest 会自动加载它,里面定义的uses(Tests\TestCase::class)是关键,否则数据库事务、HTTP 辅助方法全失效 - 首次运行
./vendor/bin/pest或php artisan test,看到绿色点就说明通了
测试 Model 时为什么 save() 不触发事件或软删除
常见现象:写了个 it('soft deletes user'),调用 $user->delete() 后查数据库发现记录没进 deleted_at,或者观察者里的 creating 根本没执行。
- 根本原因是 Pest 默认不启动 Laravel 应用上下文 —— 即使用了
uses(Tests\TestCase::class),也得确保测试类继承自Pest\Test(由pest:install自动处理),否则 Laravel 的服务容器、模型事件监听器、软删除 trait 都不会注册 - 检查
tests/Pest.php是否包含uses(Tests\TestCase::class)->in('Feature', 'Unit');;如果手动新建了测试文件在tests/Unit外,它不会被自动挂载 - Model 测试建议放
tests/Unit,但必须用RefreshDatabase或DatabaseTransactionstrait(在TestCase里已配好),否则事务不生效,assertDatabaseMissing类断言会失败
it('calls webhook') 怎么避免真实 HTTP 请求
写 Feature 测试时调用 Http::post() 或 Guzzle 直连外部服务,会导致测试慢、不稳定、依赖网络,还可能触发真实支付或通知。
- 用 Laravel 内置的
Http::fake(),不是 Mockery 也不是MockHttpClient——后者是低层抽象,容易漏掉响应结构 - 在测试开头加
Http::fake(['https://api.example.com/*' => Http::response(['ok' => true], 200)]);,路径支持通配符,响应可带 JSON、headers、status - 如果被测代码用了
new Client()或第三方 SDK(比如 Stripe SDK),Http::fake()不生效 —— 得换用Http::preventStrayRequests()配合真实 mock,或改用 SDK 自带的测试模式(如Stripe::setApiKey('sk_test_...')+Stripe::setApiBase('http://localhost')) - 别忘了验证是否真的发了请求:
Http::assertSent(function (Request $request) { return $request->url()->host() === 'api.example.com'; });
为什么 php artisan test --filter=FooTest 找不到测试
运行单个测试时提示 “No tests executed”,或报错 Class 'Tests\FooTest' not found,通常不是 Pest 问题,而是命名与文件结构不匹配。
- Pest 测试文件名必须是
*Test.php(如UserTest.php),且类名要严格对应:文件UserTest.php→ 类UserTest→ 命名空间Tests\Unit(或Tests\Feature) - 如果你用的是纯函数式写法(即没写
class UserTest),那不能用--filter按类名过滤 —— Pest 的--filter只认 PHPUnit 兼容的类/方法名,函数式测试只能用--grep(如php artisan test --grep="creates user") - 运行
./vendor/bin/pest --list-tests查看实际识别到的测试名,比猜路径更可靠 - Windows 下注意路径分隔符,
--filter中的反斜杠可能被转义,优先用正斜杠或双引号包裹
最常被忽略的一点:Pest 的函数式测试(it('does something'))不生成类,所以 IDE 跳转、静态分析、部分 CI 工具对它的支持弱于传统 PHPUnit 类写法。真要团队长期维护,别只图写得快。










