# 06. Hướng Dẫn Nâng Cao: PHP 8.4+ & Laravel 12 / 13 (Latest & Future-Proof) Tài liệu này chuẩn bị đầy đủ các kỹ thuật kiểm thử cho các phiên bản PHP và Laravel mới nhất, bao gồm **PHP 8.4**, **Laravel 12 & 13**, **PHPUnit 11/12** và **Pest PHP v3**. --- ## 1. Kiểm Thử Các Tính Năng Mới Của PHP 8.4 PHP 8.4 giới thiệu nhiều thay đổi mang tính cách mạng trong cú pháp lập trình hướng đối tượng. Unit Test cần thích ứng chính xác: ### A. Property Hooks (`get` / `set`) Thay vì viết getter/setter truyền thống hoặc Eloquent Accessor cũ, PHP 8.4 cho phép định nghĩa hooks ngay trên thuộc tính: ```php // DTO hoặc Model trong PHP 8.4 class UserProfile { public string $firstName; public string $lastName; // Property Hook tự động tính toán public string $fullName { get => trim("{$this->firstName} {$this->lastName}"); } // Property Hook kiểm soát gán giá trị public string $email { set { if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { throw new \InvalidArgumentException('Email không hợp lệ'); } $this->email = strtolower($value); } } } ``` #### Cách viết Unit Test: ```php #[Test] public function it_calculates_full_name_via_property_hook(): void { $profile = new UserProfile(); $profile->firstName = 'Thien'; $profile->lastName = 'Phan'; // Kiểm thử get hook $this->assertSame('Thien Phan', $profile->fullName); } #[Test] public function it_throws_exception_when_setting_invalid_email_hook(): void { $profile = new UserProfile(); $this->expectException(\InvalidArgumentException::class); // Kiểm thử set hook $profile->email = 'invalid-email-format'; } ``` ### B. Asymmetric Visibility (`public private(set)`) PHP 8.4 cho phép thuộc tính có quyền đọc công khai nhưng chỉ được sửa từ bên trong class: ```php class BankAccount { // Đọc public từ ngoài, nhưng chỉ private method được set public private(set) int $balance = 0; public function deposit(int $amount): void { if ($amount <= 0) { throw new \InvalidArgumentException('Số tiền nạp phải > 0'); } $this->balance += $amount; } } ``` #### Cách viết Unit Test: ```php #[Test] public function it_updates_balance_via_public_api_and_allows_public_reading(): void { $account = new BankAccount(); // Đọc trạng thái ban đầu $this->assertSame(0, $account->balance); // Kích hoạt method hợp lệ $account->deposit(500_000); $this->assertSame(500_000, $account->balance); // Cố tình ghi đè từ ngoài sẽ gây Error (PHP Fatal Error) // Unit test tập trung xác nhận method nội bộ thay đổi đúng giá trị } ``` ### C. Hàm Array Mới (`array_find`, `array_any`, `array_all`) Kiểm thử các business logic sử dụng các hàm tiện ích mảng mới của PHP 8.4. --- ## 2. Kiểm Thử Kiến Trúc Laravel Hiện Đại (Laravel 11, 12, 13) ### A. Concurrency API (`Concurrency::fake()`) Từ Laravel 11 và tiếp tục hoàn thiện trên Laravel 12/13, Laravel cung cấp Facade `Concurrency` để chạy các tác vụ song song: ```php // Trong Service public function fetchDashboardData(): array { return Concurrency::run([ fn () => $this->userService->getStats(), fn () => $this->orderService->getRevenue(), ]); } ``` #### Cách viết Unit Test: ```php use Illuminate\Support\Facades\Concurrency; #[Test] public function it_executes_concurrent_tasks_correctly(): void { // Giả lập Concurrency để chạy tuần tự trong lúc test Concurrency::fake(); $dashboardData = $dashboardService->fetchDashboardData(); $this->assertCount(2, $dashboardData); } ``` ### B. Context API (`Context::fake()`) Laravel Context cho phép theo dõi metadata xuyên suốt vòng đời request và background jobs: ```php use Illuminate\Support\Facades\Context; #[Test] public function it_attaches_trace_id_to_context(): void { $middleware = new TraceContextMiddleware(); $request = Request::create('/api/orders', 'GET'); $request->headers->set('X-Trace-ID', 'trace-xyz-123'); $middleware->handle($request, fn () => response('OK')); $this->assertSame('trace-xyz-123', Context::get('trace_id')); } ``` --- ## 3. Pest PHP v3: Architecture Testing (`arch()`) Trong các dự án Laravel 11/12/13 hiện đại dùng Pest v3, ngoài việc test từng method, chúng ta có thể viết **Architectural Tests** để kiểm soát toàn bộ cấu trúc code: ```php // tests/Unit/ArchitectureTest.php describe('Architecture Rules', function () { test('Controllers do not directly use Models (must use Services/Actions)') ->expect('App\Http\Controllers') ->not->toUse('App\Models') ->ignoring('App\Http\Controllers\Auth'); test('Services must be readonly or final') ->expect('App\Services') ->toBeFinal(); test('All Value Objects must be immutable') ->expect('App\ValueObjects') ->toBeReadonly(); test('No debugging functions left in code') ->expect(['dd', 'dump', 'ray', 'var_dump']) ->not->toBeUsed(); }); ``` --- ## 4. Tương Thích PHPUnit 11 & 12 1. **Loại bỏ hoàn toàn DocBlock**: PHPUnit 11+ deprecate và loại bỏ chú thích dạng `@test`, `@dataProvider`. Bắt buộc 100% sử dụng: - `#[PHPUnit\Framework\Attributes\Test]` - `#[PHPUnit\Framework\Attributes\DataProvider('providerMethod')]` - `#[PHPUnit\Framework\Attributes\TestDox('Mô tả tiếng Việt dễ đọc')]` 2. **Event-driven Internal System**: PHPUnit 11 quản lý vòng đời test hoàn toàn bằng sự kiện, giúp execution nhanh hơn và đo lường chính xác hơn.