PHPUnit 是 Laravel 默认测试框架,测试类须继承 Tests\TestCase 才能使用 refreshDatabase() 等方法;测试文件放 tests/Feature/,命名以 test 开头,可用 php artisan test --filter 运行指定测试。

PHPUnit 是 Laravel 默认集成的测试框架,所有测试用例都必须继承 Illuminate\Foundation\Testing\TestCase 或其子类(如 Tests\TestCase),否则 refreshDatabase()、actingAs() 等辅助方法不可用。
如何创建并运行一个基础功能测试
Laravel 的测试文件默认放在 tests/Feature/ 目录下,使用 php artisan make:test UserRegistrationTest 生成后,需确保类继承自 Tests\TestCase。测试方法名必须以 test 开头,否则 PHPUnit 不会识别为测试用例。
- 运行单个测试:
php artisan test --filter=UserRegistrationTest - 运行某个测试方法:
php artisan test --filter=test_user_can_register - 不加
--filter时,php artisan test会自动扫描tests/下所有*Test.php文件 - 若测试中调用
$this->get('/')报错 “Target class [App\Http\Controllers\HomeController] does not exist”,说明路由未启用或控制器命名空间错误——检查routes/web.php是否注册了该路由,且控制器路径与app/Http/Controllers/下实际位置一致
数据库迁移与测试数据隔离的关键配置
功能测试常依赖真实数据库行为,但又不能污染开发环境数据。Laravel 提供两种主流方式:RefreshDatabase 和 DatabaseMigrations,二者均通过 Trait 注入,但底层行为不同。
-
RefreshDatabase:每次测试前清空所有表(truncate),再重建迁移(up),适合大多数场景;它不执行seeders,除非显式调用$this->seed() -
DatabaseMigrations:每次测试前执行migrate:fresh,即先down再up,速度略慢,但能确保外键约束和初始状态完全一致 - 若测试中使用了
factory()->create(),注意 Laravel 8+ 已弃用全局factory()函数,应改用User::factory()->create() - 在
phpunit.xml中确认DB_CONNECTION环境变量指向testing数据库(如 SQLite 内存库:memory:),避免误操作本地 MySQL
模拟 HTTP 请求与断言响应的常见写法
Laravel 测试中发起请求不是直接调用控制器方法,而是走完整 HTTP 生命周期(中间件、路由、控制器),因此可真实验证权限、重定向、JSON 结构等。
立即学习“PHP免费学习笔记(深入)”;
- GET 请求并断言状态码:
$response = $this->get('/users'); $response->assertStatus(200); - POST 表单提交并验证重定向:
$this->post('/register', ['name' => 'Alice', 'email' => 'a@example.com'])->assertRedirect('/dashboard'); - 发送 JSON 请求:
$this->json('POST', '/api/posts', ['title' => 'Test'])->assertJson(['message' => 'Created']); - 断言视图渲染内容:
$response->assertViewIs('users.index')->assertViewHas('users', function ($collection) { return $collection->count() === 3; }); - 若断言失败提示 “Expected status code 200, got 500”,优先检查日志:
storage/logs/test.log,常见原因是模型事件监听器抛异常、未配置APP_KEY导致加密失败,或队列驱动设为sync以外却未启动 Redis
use Tests\TestCase;
use App\Models\User;
class UserRegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_register()
{
$response = $this->post('/register', [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$response->assertRedirect('/dashboard');
$this->assertDatabaseHas('users', [
'email' => 'john@example.com',
]);
}
}
真正容易被忽略的是测试环境的配置一致性——比如 config/cache.php 中 default 值在 testing 环境下是否强制设为 array,否则 Redis 缓存未就绪会导致测试随机失败;还有 APP_URL 必须设为有效 URL(如 http://localhost),否则生成的签名 URL 或邮件链接会出错。











