2045c856e9
- Add 10 core testing guides (setup, AAA principles, PHPUnit/Pest, mocking, anti-patterns, PHP 8.4+, debugging, data factories, advanced edge cases) - Add 13 component testing guides covering all Laravel layers - Add standard templates for PHPUnit 10/11 and Pest v2/v3 including ArchitectureTest - Add Docker smart test runner, dependency installer, and CI/CD templates (GitHub Actions, GitLab CI) - Add 4 Claude Code skills (laravel-test-setup, laravel-unit-test with --all mode, laravel-test-review, laravel-mock-helper) - Add single unified installer script (sg-install-unit-testing.sh) with global support, CLI runners, and 1-click updater (sg-test-update) - Add comprehensive documentation (README.md, USAGE-GUIDE.md) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
112 lines
3.2 KiB
Markdown
112 lines
3.2 KiB
Markdown
# Component Guide: Queueable Jobs
|
|
|
|
Jobs xử lý các tác vụ nền không đồng bộ (Asynchronous Background Tasks) như gửi email hàng loạt, xử lý file nặng, đồng bộ dữ liệu.
|
|
|
|
---
|
|
|
|
## 1. Hai Mức Độ Kiểm Thử Cho Jobs
|
|
|
|
1. **Kiểm thử Dispatching (Job được đẩy vào hàng đợi đúng lúc không?)**:
|
|
- Dùng `Queue::fake()` trong Service/Controller test.
|
|
- Xác nhận `Queue::assertPushed(MyJob::class)`.
|
|
2. **Kiểm thử Thực Thi (Unit Test trực tiếp method `handle()` của Job)**:
|
|
- Đây chính là đối tượng của Unit Test Job.
|
|
- Khởi tạo trực tiếp đối tượng `$job = new ProcessPaymentJob(...)`.
|
|
- Inject mock dependencies vào method `handle()`.
|
|
- Kiểm tra xem Job có thực thi logic và gọi service đúng không.
|
|
- Kiểm tra method `failed(\Throwable $exception)` khi gặp sự cố.
|
|
|
|
---
|
|
|
|
## 2. Mã Mẫu Chuẩn: Job Unit Test
|
|
|
|
### Job Nguồn: `App\Jobs\SendWelcomeEmailJob`
|
|
```php
|
|
namespace App\Jobs;
|
|
|
|
use App\Contracts\MailerInterface;
|
|
use App\Models\User;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
class SendWelcomeEmailJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
public int $tries = 3;
|
|
|
|
public function __construct(
|
|
public readonly User $user
|
|
) {}
|
|
|
|
public function handle(MailerInterface $mailer): void
|
|
{
|
|
$mailer->sendWelcome($this->user->email, $this->user->name);
|
|
}
|
|
|
|
public function failed(?\Throwable $exception): void
|
|
{
|
|
\Illuminate\Support\Facades\Log::error("Failed to send welcome email to user {$this->user->id}");
|
|
}
|
|
}
|
|
```
|
|
|
|
### Test Chuẩn: PHPUnit 10+
|
|
```php
|
|
namespace Tests\Unit\Jobs;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Mockery;
|
|
use App\Jobs\SendWelcomeEmailJob;
|
|
use App\Contracts\MailerInterface;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class SendWelcomeEmailJobTest extends TestCase
|
|
{
|
|
protected function tearDown(): void
|
|
{
|
|
Mockery::close();
|
|
parent::tearDown();
|
|
}
|
|
|
|
#[Test]
|
|
public function it_sends_welcome_email_when_handled(): void
|
|
{
|
|
// Arrange
|
|
$user = new User(['id' => 10, 'name' => 'Thien', 'email' => 'thien@example.com']);
|
|
$mailerMock = Mockery::mock(MailerInterface::class);
|
|
$mailerMock->shouldReceive('sendWelcome')
|
|
->once()
|
|
->with('thien@example.com', 'Thien');
|
|
|
|
$job = new SendWelcomeEmailJob($user);
|
|
|
|
// Act
|
|
$job->handle($mailerMock);
|
|
|
|
// Assert: Mockery tự động verify qua expectation ->once()
|
|
$this->assertTrue(true);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_logs_error_when_job_fails(): void
|
|
{
|
|
// Arrange
|
|
$user = new User(['id' => 10, 'name' => 'Thien', 'email' => 'thien@example.com']);
|
|
$job = new SendWelcomeEmailJob($user);
|
|
|
|
Log::shouldReceive('error')
|
|
->once()
|
|
->with('Failed to send welcome email to user 10');
|
|
|
|
// Act
|
|
$job->failed(new \RuntimeException('SMTP Connection Timeout'));
|
|
}
|
|
}
|
|
```
|