Vì sao Testing trong Laravel quan trọng?
Rất nhiều project Laravel bỏ qua testing ở giai đoạn đầu. Nhưng khi hệ thống lớn dần:
- Refactor trở nên nguy hiểm
- Fix bug dễ sinh bug mới
- Onboard dev mới mất nhiều thời gian
Testing giúp bạn:
- Tự tin thay đổi code
- Giảm regression
- Giữ chất lượng code ổn định
Tài liệu chính thức:
https://laravel.com/docs/testing
1️⃣ Cấu trúc Testing trong Laravel
Laravel được build trên PHPUnit và có sẵn cấu trúc:
tests/
├── Feature/
├── Unit/
Unit Test
- Test logic nhỏ
- Không test HTTP
- Chạy nhanh
Feature Test
- Test request/response
- Test API
- Test full flow
2️⃣ Viết Unit Test cho Service
Giả sử bạn có service:
class CalculateDiscount
{
public function execute(int $price): int
{
return $price * 0.9;
}
}
Tạo test:
php artisan make:test CalculateDiscountTest --unit
Viết test:
public function test_it_calculates_discount_correctly()
{
$service = new CalculateDiscount(); $result = $service->execute(100); $this->assertEquals(90, $result);
}
Unit test nên:
- Không phụ thuộc database
- Không call API ngoài
- Không gửi mail thật
3️⃣ Feature Test cho API
Ví dụ test endpoint đăng ký user:
public function test_user_can_register()
{
$response = $this->postJson('/api/register', [
'name' => 'John',
'email' => 'john@example.com',
'password' => 'password'
]); $response->assertStatus(201); $this->assertDatabaseHas('users', [
'email' => 'john@example.com'
]);
}
Laravel cung cấp nhiều helper:
- assertStatus
- assertJson
- assertDatabaseHas
- assertSee
Giúp test rất rõ ràng và dễ đọc.
4️⃣ Database Testing với RefreshDatabase
Laravel hỗ trợ reset database tự động trong test.
use Illuminate\Foundation\Testing\RefreshDatabase;
Trait này sẽ:
- Rollback transaction
hoặc - Migrate lại database cho mỗi test
Đảm bảo mỗi test độc lập và không ảnh hưởng lẫn nhau.
5️⃣ Mock Dependency với Service Container
Nếu bạn đã áp dụng Dependency Injection, việc mock rất dễ.
$this->mock(PaymentService::class, function ($mock) {
$mock->shouldReceive('charge')
->once()
->andReturn(true);
});
Laravel sử dụng Mockery phía dưới.
Tài liệu mocking:
https://laravel.com/docs/mocking
Mock giúp:
- Không gọi API thật
- Không gửi email thật
- Không phụ thuộc service ngoài
6️⃣ Testing Authorization
Testing phân quyền cực kỳ quan trọng để tránh data leak.
Ví dụ:
public function test_user_cannot_update_other_user_post()
{
$user = User::factory()->create();
$otherUser = User::factory()->create(); $post = Post::factory()->create([
'user_id' => $otherUser->id
]); $this->actingAs($user)
->put("/posts/{$post->id}")
->assertStatus(403);
}
Nếu không test authorization, bạn có thể vô tình mở quyền sai trong production.
7️⃣ TDD trong Laravel
TDD (Test Driven Development) gồm 3 bước:
- Viết test trước
- Chạy test (fail)
- Viết code để pass
- Refactor
Laravel rất phù hợp cho TDD vì:
- Có artisan tạo test nhanh
- Có factory tạo data
- Có HTTP test helper
Ví dụ tạo factory:
php artisan make:factory UserFactory
Factory giúp generate dữ liệu test dễ dàng.
8️⃣ Chạy Test trong CI
Trong production, test nên chạy tự động khi push code.
Chạy test:
php artisan test
Hoặc:
vendor/bin/phpunit
Tích hợp với:
- GitHub Actions
- GitLab CI
- Azure Pipeline
Mỗi lần commit → test chạy → giảm rủi ro merge bug vào production.
Kết luận
Testing trong Laravel không hề phức tạp. Ngược lại, đây là một trong những hệ thống test dễ tiếp cận nhất trong PHP.
Để nâng level:
- Viết unit test cho business logic
- Viết feature test cho API
- Test authorization
- Mock dependency đúng cách
- Tích hợp CI
