0dce2ef812
- Enforce mandatory handle() and failed() method testing for all Jobs and Commands - Ban shallow reflection-only helper testing in Jobs - Mandate actual SQLite in-memory query execution for Repositories (ban Builder::class assertions alone) - Enforce full branch coverage for SonarQube (ternary, null-coalescing, catch blocks, match) - Update JobTest templates for PHPUnit and Pest to include handle() and failed() methods - Update verification checklist and master system prompt with strict branch gatekeepers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.2 KiB
4.2 KiB
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
- 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).
- Dùng
- 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
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+
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'));
}
}
3. Bẫy Nghiêm Trọng Cần Tránh Khi Test Jobs
❌ Bẫy Anti-Pattern: Chỉ dùng Reflection test hàm helper nhỏ
Nhiều AI và lập trình viên hay dùng ReflectionMethod để test các hàm helper nhỏ như buildRedisKey(), getFilePath() và bỏ qua hoàn toàn phương thức chính handle().
- Hậu quả: SonarQube báo độ phủ của Job chỉ đạt 1% - 10%, vì 90% dòng code nằm trong
handle()không hề được chạy! - Quy tắc vàng:
- BẮT BUỘC 100% phải test method
handle(). - Mock toàn bộ dependencies của
handle(): Storage (Storage::fake()), Database/Repository, Redis (Redis::shouldReceive()), Mailer. - Phải có bài test cho các trường hợp rẽ nhánh trong
handle(): khi dữ liệu rỗng, khi export thành công, khi import lỗi từng dòng. - Phải có bài test gọi method
failed(?Throwable $e)để kiểm tra việc ghi log hoặc bắn alert khi job thất bại.
- BẮT BUỘC 100% phải test method