直接运行 php artisan test 即可启动 PHPUnit 测试,需确保 PHP ≥8.0、phpunit.xml 存在且 composer autoload 已刷新;测试类应继承 tests/TestCase.php;数据库测试推荐用 RefreshDatabase trait 并配置专用连接。

怎么在 Laravel 里跑起第一个 PHPUnit 测试
直接运行 php artisan test 就能启动测试,但前提是项目已装好 phpunit/phpunit(Laravel 9+ 默认内置,8.x 需手动安装)。别急着写测试,先确认环境:PHP 版本得 ≥8.0(Laravel 9+),且 phpunit.xml 在项目根目录存在——它控制了自动加载、测试路径和全局配置。
常见错误现象:Class 'Tests\TestCase' not found,大概率是 composer autoload 没刷新,执行 composer dump-autoload 再试;或者 tests/TestCase.php 被误删了(它是所有测试类的基类,不能少)。
- 新项目默认用
tests/Feature放 HTTP 请求类测试,tests/Unit放模型、服务等隔离逻辑测试 -
php artisan make:test UserTest --unit会生成到Unit目录,加--feature才进Feature - 别把数据库迁移塞进
setUp()——用RefreshDatabasetrait 更稳,它每次测试后重置 DB,避免状态污染
测试数据库操作时为什么数据没清干净
因为 RefreshDatabase 只对 sqlite:memory 或带 --database=testing 的连接生效。如果你的 phpunit.xml 里 DB_CONNECTION 还指向 mysql,那它只是“假装清库”,实际连的是开发库——这非常危险。
正确做法是:在 phpunit.xml 中显式设置测试专用数据库连接:
<env name="DB_CONNECTION" value="sqlite"></env><env name="DB_DATABASE" value=":memory:"></env>
或者用 MySQL 时配独立库名:
<env name="DB_CONNECTION" value="mysql"></env><env name="DB_DATABASE" value="laravel_test"></env>
-
:memory:最快,但不支持外键约束(比如你用了foreignId+constrained(),得切回文件 SQLite 或 MySQL) - 用 MySQL 测试库必须提前建好(
CREATE DATABASE laravel_test;),且用户要有权限 - 别在测试里手动
DB::table('users')->truncate()——它绕过 Eloquent 事件,也破坏RefreshDatabase的事务机制
怎么测一个带 Auth 的 API 接口
关键不是“怎么登录”,而是“怎么跳过中间件却保留认证状态”。直接调 postJson('/api/posts') 会 401,因为 auth:sanctum 拦住了。正确姿势是用 $this->actingAs($user) 或 $this->withToken($token)。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
示例:测需要 Sanctum token 的接口
$user = User::factory()->create();
$token = $user->createToken('test')->plainTextToken;
$this->withToken($token)
->getJson('/api/user')
->assertOk();
-
actingAs()适合 Session 登录(Web 路由),对 API 路由无效;API 必须用withToken() -
createToken()返回的是SanctumToken实例,plainTextToken才是发给前端的真实字符串 - 别用
Auth::login($user)—— 它只影响当前请求生命周期,下个getJson()就失效
测试中 mock 依赖为什么总是不生效
因为你 mock 的对象没真正被注入到被测类里。Laravel 的 Service Container 管理实例,直接 $mock = Mockery::mock(...) 不会自动替换容器中的绑定。
必须用 $this->mock()(测试基类提供)或手动 $this->app->instance():
$mock = Mockery::mock(EmailService::class); $this->app->instance(EmailService::class, $mock); // 然后触发业务逻辑,比如 $order->ship() $order = Order::factory()->create(); $order->ship(); // 这时才会调 mock 的 send() 方法 $mock->shouldHaveReceived()->send();
- 用
$this->mock(EmailService::class)更简洁,它底层就是帮你做了instance() - 别在
setUp()里 mock 全局类(如Cache),优先用Cache::shouldReceive()静态 mock - Mockery 默认 strict,如果方法没声明就调用会报错;加
->makePartial()可只 mock 部分方法
最常被忽略的是:测试结束后没 Mockery::close(),导致下一个测试拿到残留 mock。Laravel 的 TestCase 已在 tearDown() 自动调了,但如果你自己 new 了 Mockery mock,就得手动关。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










