Laravel中如何进行单元测试_Laravel使用PHPUnit编写测试用例【实战】

9次阅读

phpUnit 是 laravel 默认测试框架,测试类须继承 TestsTestCase 才能使用 refreshDatabase() 等方法;测试文件放 tests/Feature/,命名以 test 开头,可用 php artisan test –Filter 运行指定测试。

Laravel中如何进行单元测试_Laravel使用PHPUnit编写测试用例【实战】

PHPUnit 是 Laravel 默认集成的测试框架,所有测试用例都必须继承 IlluminateFoundationTestingTestCase 或其子类(如 TestsTestCase),否则 refreshDatabase()actingAs() 等辅助方法不可用。

如何创建并运行一个基础功能测试

Laravel 的测试文件默认放在 tests/Feature/ 目录下,使用 php artisan make:test UserRegistrationTest 生成后,需确保类继承自 TestsTestCase。测试方法名必须以 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 [apphttpControllersHomeController] does not exist”,说明路由未启用或控制器命名空间错误——检查 routes/web.php 是否注册了该路由,且控制器路径与 app/Http/Controllers/ 下实际位置一致

数据库迁移与测试数据隔离的关键配置

功能测试常依赖真实数据库行为,但又不能污染开发环境数据。Laravel 提供两种主流方式:RefreshDatabaseDatabaseMigrations,二者均通过 Trait 注入,但底层行为不同。

  • RefreshDatabase:每次测试前清空所有表(truncate),再重建迁移(up),适合大多数场景;它不执行 seeders,除非显式调用 $this->seed()
  • DatabaseMigrations:每次测试前执行 migrate:fresh,即先 downup,速度略慢,但能确保外键约束和初始状态完全一致
  • 若测试中使用了 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 TestsTestCase; use AppModelsUser;  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.phpdefault 值在 testing 环境下是否强制设为 Array,否则 Redis 缓存未就绪会导致测试随机失败;还有 APP_URL 必须设为有效 URL(如 http://localhost),否则生成的签名 URL 或邮件链接会出错。

text=ZqhQzanResources