laravel单元测试专注单个类或方法逻辑,使用phpUnit集成,测试文件置于tests/Unit/目录,类名以Test结尾、方法以test_开头,不依赖http请求或数据库,可用Mockery模拟外部依赖。

在 Laravel 中编写单元测试和功能测试,核心是利用内置的 PHPUnit 集成和丰富的测试辅助方法。Laravel 默认已配置好 phpunit.xml,测试文件放在 tests/ 目录下,通过 php artisan test(或 vendor/bin/phpunit)运行。
单元测试:专注单个类或方法逻辑
单元测试验证模型、服务类、帮助函数等不依赖 HTTP 请求或数据库(或使用内存数据库/模拟)的独立逻辑。Laravel 提供 TestCase 基类,但单元测试通常继承更轻量的 TestsTestCase 或直接用 PHPUnitFrameworkTestCase。
- 将测试类放在
tests/Unit/目录下,类名以Test结尾(如CalculatorTest.php) - 方法名以
test_开头或用@test注释标记 - 避免使用
$this->get()、$this->actingAs()等 HTTP 相关方法 - 如需隔离外部依赖,用
Mockery模拟(Laravel 自带)或 PHP 的createMock()
示例(测试一个简单的服务类):
// tests/Unit/PriceCalculatorTest.php <?php namespace TestsUnit; use AppServicesPriceCalculator; use PHPUnitFrameworkTestCase; class PriceCalculatorTest extends TestCase { public function test_calculates_total_with_tax() { $calculator = new PriceCalculator(); $total = $calculator->withTax(100, 0.15); $this->assertEquals(115, $total); } }
功能测试:模拟真实 HTTP 请求与用户交互
功能测试(也称“特性测试”)验证整个请求生命周期:路由 → 控制器 → 视图/响应,常涉及数据库、认证、会话等。Laravel 的 TestsTestCase 提供了开箱即用的测试工具链。
立即学习“PHP免费学习笔记(深入)”;
- 测试类放在
tests/Feature/目录下 - 默认启用数据库迁移(每次测试前重置
sqlite:memory),也可用@database注解或RefreshDatabasetrait - 常用断言:
$this->get()、$this->post()、$this->assertStatus(200)、$this->assertSee('Welcome')、$this->assertJson(...) - 登录用户可用
$this->actingAs($user),无需真实 session
示例(测试文章列表页):
// tests/Feature/ArticleIndexTest.php <?php namespace TestsFeature; use AppModelsArticle; use IlluminateFoundationTestingRefreshDatabase; use TestsTestCase; class ArticleIndexTest extends TestCase { use RefreshDatabase; public function test_articles_page_returns_successful_response() { Article::factory()->count(3)->create(); $response = $this->get('/articles'); $response->assertStatus(200); $response->assertSee('Articles'); $response->assertSeeText('Article Title 1'); $response->assertJsonCount(3, 'data'); } }
数据库测试技巧:工厂、种子与事务控制
Laravel 测试中操作数据库最推荐的方式是模型工厂(Factories)+ RefreshDatabase trait,它自动在每个测试前后用事务回滚,速度快且隔离性好。
- 用
Article::factory()->create()创建测试数据,支持属性覆盖:['title' => 'Test'] - 批量创建:
Article::factory()->count(5)->create() - 关联数据可链式调用:
User::factory()->hasPosts(3)->create() - 避免在测试中手动写
DB::table(...)->insert(...),破坏可读性和维护性 - 如需完整迁移(比如测试迁移本身),用
UsesTransactions替换或禁用RefreshDatabase
运行与调试测试的实用建议
- 只运行某个测试类:
php artisan test --Filter ArticleIndexTest - 只运行某个方法:
php artisan test --filter test_articles_page_returns_successful_response - 查看详细输出(含异常堆栈):
php artisan test -v - 生成覆盖率报告(需安装 Xdebug 或 PCOV):
php artisan test --coverage-html coverage - 失败时快速定位:检查是否忘记
use RefreshDatabase;,或模型未加$fillable导致工厂创建失败
基本上就这些。Laravel 的测试体验流畅,关键在于分清单元与功能的边界,善用工厂和测试 trait,让测试既可靠又易维护。