Laravel Testing 2026: Pest, Mocking va Cau Hoi Phong Van Ky Thuat

Huong dan toan dien ve kiem thu Laravel voi Pest trong nam 2026: unit test, feature test, mocking facade, architecture test, mutation testing va cac cau hoi phong van ky thuat danh cho lap trinh vien PHP.

Huong dan kiem thu Laravel voi Pest bao gom mocking, architecture test va cau hoi phong van ky thuat 2026

Kiểm thử phần mềm trong hệ sinh thái Laravel đã trải qua những bước chuyển đổi đáng kể trong vài năm gần đây. Nếu như trước đây PHPUnit là lựa chọn duy nhất, thì đến năm 2026, Pest đã khẳng định vị thế là framework kiểm thử chuẩn trong cộng đồng Laravel. Với phiên bản Pest 4, các tính năng như architecture testing, mutation testing và cú pháp expressive đã được nâng cấp đáng kể, mang lại trải nghiệm viết test nhanh hơn và dễ đọc hơn. Trong các buổi phỏng vấn kỹ thuật Laravel, khả năng viết test chuyên nghiệp với Pest, thành thạo mocking và hiểu rõ các chiến lược kiểm thử là những tiêu chí được đánh giá hàng đầu.

Bài viết này phân tích chi tiết các kỹ thuật kiểm thử Laravel với Pest, từ cấu hình ban đầu đến mutation testing, bao gồm mocking facade, mocking với Mockery, architecture testing và các mẫu kiểm thử database. Mỗi phần đều đi kèm ví dụ code cụ thể, có thể áp dụng trực tiếp vào dự án thực tế hoặc bài tập phỏng vấn.

Pest 4 đã trở thành chuẩn mực kiểm thử Laravel

Pest được xây dựng trên nền tảng PHPUnit nhưng cung cấp cú pháp expressive lấy cảm hứng từ Jest và RSpec. Chuỗi expect()->toBe() thay thế các assertion truyền thống như assertEquals(), các khối describe/it tổ chức test một cách trực quan, và các tính năng tích hợp sẵn như architecture testing và mutation testing giảm thiểu sự phụ thuộc vào package bên ngoài. Mọi test PHPUnit hiện có đều hoạt động bình thường trong một suite Pest mà không cần chỉnh sửa.

Cấu Hình Pest 4 Trong Dự Án Laravel 12

Việc cấu hình Pest trong dự án Laravel tập trung vào file tests/Pest.php, nơi định nghĩa các trait và class cơ sở được áp dụng tự động cho toàn bộ file test. Việc tập trung hóa này loại bỏ sự lặp lại các khai báo chung và đảm bảo tính nhất quán của môi trường kiểm thử trong toàn bộ suite.

tests/Pest.phpphp
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()
    ->extend(Tests\TestCase::class)
    ->use(RefreshDatabase::class)
    ->in('Feature');

Phương thức extend() liên kết class TestCase của Laravel với tất cả các test, cung cấp quyền truy cập vào các phương thức HTTP (getJson, postJson), xác thực giả lập (actingAs) và các assertion response. Trait RefreshDatabase khôi phục cơ sở dữ liệu giữa mỗi test thông qua transaction, đảm bảo sự cô lập hoàn toàn mà không tốn chi phí chạy lại migration mỗi lần thực thi.

Chỉ thị ->in('Feature') giới hạn phạm vi áp dụng cấu hình này cho các feature test. Các unit test trong thư mục tests/Unit/ sử dụng môi trường nhẹ hơn, không kết nối cơ sở dữ liệu, giúp tăng tốc độ thực thi. Sự tách biệt kiến trúc giữa unit test và feature test phản ánh kim tự tháp kiểm thử cổ điển và là điểm đánh giá phổ biến trong phỏng vấn kỹ thuật.

Unit Test và Feature Test

Feature Test: Xác Thực Endpoint HTTP

Feature test trong Laravel kiểm tra toàn bộ hành vi của một endpoint, từ request HTTP đầu vào cho đến response JSON hoặc redirect. Pest đơn giản hóa việc viết các test này nhờ cú pháp fluent cho phép chain các assertion về status, cấu trúc JSON và kiểm tra cơ sở dữ liệu.

tests/Feature/UserRegistrationTest.phpphp
use App\Models\User;

it('registers a new user with valid data', function () {
    $response = $this->postJson('/api/register', [
        'name' => 'Jane Doe',
        'email' => 'jane@example.com',
        'password' => 'SecurePass123!',
        'password_confirmation' => 'SecurePass123!',
    ]);

    $response->assertStatus(201)
        ->assertJsonStructure(['user' => ['id', 'name', 'email']]);

    expect(User::where('email', 'jane@example.com')->exists())->toBeTrue();
});

Phương thức postJson() gửi request POST với header JSON được cấu hình tự động, mô phỏng một API client thực tế. Assertion assertJsonStructure xác thực sự hiện diện của các key mong đợi mà không áp đặt giá trị cụ thể, giúp test linh hoạt trước các thay đổi nhỏ của response. Assertion cuối cùng qua expect() xác nhận rằng người dùng đã được lưu vào cơ sở dữ liệu, kiểm tra toàn bộ chuỗi xử lý từ routing, middleware, validation, controller logic đến persistence.

Unit Test: Logic Nghiệp Vụ Cô Lập

Unit test nhắm vào các class hoặc phương thức riêng lẻ, không tương tác với cơ sở dữ liệu, hệ thống file hoặc dịch vụ bên ngoài. Chúng thực thi trong vài mili giây và tạo nên nền tảng đáng tin cậy nhất của kim tự tháp kiểm thử.

tests/Unit/PriceCalculatorTest.phpphp
use App\Services\PriceCalculator;

describe('PriceCalculator', function () {
    it('applies a percentage discount correctly', function () {
        $calculator = new PriceCalculator();

        // 20% off a 150.00 base price
        $result = $calculator->applyDiscount(150.00, 20);

        expect($result)->toBe(120.00);
    });

    it('rejects negative discount values', function () {
        $calculator = new PriceCalculator();

        expect(fn () => $calculator->applyDiscount(100.00, -5))
            ->toThrow(InvalidArgumentException::class);
    });
});

Khối describe nhóm các test liên quan đến cùng một class hoặc tính năng, giúp báo cáo thực thi dễ đọc hơn. Assertion toThrow() xác nhận rằng exception được throw đúng cách cho các đầu vào không hợp lệ — một pattern phòng thủ thiết yếu trong logic nghiệp vụ. Việc truyền closure vào expect() cho phép bắt exception mà không làm gián đoạn test.

Trong phỏng vấn kỹ thuật, khả năng phân biệt đâu là unit test (logic tính toán, chuyển đổi dữ liệu, validation quy tắc nghiệp vụ) và đâu là feature test (tương tác HTTP, tích hợp cơ sở dữ liệu) là một chỉ số quan trọng về mức độ trưởng thành kỹ thuật.

Mocking Với Facade và Mockery

Mocking Facade Laravel: Mail, Queue và Notification

Laravel cung cấp hệ thống facade giúp đơn giản hóa việc truy cập các service của framework. Trong kiểm thử, các facade cung cấp phương thức fake() thay thế implementation thực bằng một test double có khả năng ghi lại các lệnh gọi mà không tạo ra tác dụng phụ. Cơ chế này là nền tảng để kiểm thử các quy trình gửi email, dispatch job hoặc trigger notification.

tests/Feature/OrderProcessingTest.phpphp
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
use App\Mail\OrderConfirmation;
use App\Jobs\ProcessPayment;

it('dispatches payment job and sends confirmation email', function () {
    // Fake both Mail and Queue facades
    Mail::fake();
    Queue::fake();

    $user = User::factory()->create();
    $order = Order::factory()->for($user)->create([
        'total' => 99.99,
        'status' => 'pending',
    ]);

    // Act: confirm the order via HTTP
    $this->actingAs($user)
        ->postJson("/api/orders/{$order->id}/confirm")
        ->assertOk();

    // Assert: payment job was dispatched with correct amount
    Queue::assertPushed(ProcessPayment::class, function ($job) use ($order) {
        return $job->order->id === $order->id
            && $job->order->total === 99.99;
    });

    // Assert: confirmation email was sent to the user
    Mail::assertSent(OrderConfirmation::class, function ($mail) use ($user) {
        return $mail->hasTo($user->email);
    });
});

Lệnh gọi Mail::fake()Queue::fake() chặn tương ứng việc gửi email và dispatch job trong suốt thời gian test. Không có email thực nào được gửi, không có job nào được thực thi. Các assertion assertPushedassertSent sau đó xác minh rằng đúng class đã được dispatch với các tham số mong đợi.

Closure truyền vào Queue::assertPushed minh họa một pattern nâng cao: cho phép xác minh không chỉ job đã được dispatch, mà còn các thuộc tính của nó chứa đúng giá trị. Mức độ chi tiết này giúp phát hiện các lỗi tinh vi khi đối tượng sai được truyền cho job — lỗi thường gặp trong quá trình refactoring.

Mocking Nâng Cao Với Mockery: Dịch Vụ Bên Ngoài

Đối với các service không phải facade Laravel, Mockery cung cấp khả năng kiểm soát chi tiết hành vi của test double. Trường hợp này thường gặp với các client của dịch vụ bên thứ ba như Stripe, Twilio hoặc các API nội bộ.

tests/Feature/PaymentGatewayTest.phpphp
use App\Services\PaymentGateway;
use App\Services\StripeClient;

it('charges the customer through the payment gateway', function () {
    // Create a mock of the Stripe client
    $stripeClient = Mockery::mock(StripeClient::class);
    $stripeClient->shouldReceive('charge')
        ->once()
        ->with('cus_abc123', 5000, 'usd')
        ->andReturn(['status' => 'succeeded', 'id' => 'ch_xyz']);

    // Bind the mock in the container
    $this->app->instance(StripeClient::class, $stripeClient);

    $gateway = app(PaymentGateway::class);
    $result = $gateway->processCharge('cus_abc123', 50.00);

    expect($result['status'])->toBe('succeeded');
});

Phương thức Mockery::mock() tạo ra một test double chặn các lệnh gọi phương thức. Chuỗi shouldReceive()->once()->with()->andReturn() định nghĩa một hợp đồng chặt chẽ: phương thức charge phải được gọi đúng một lần, với các tham số chỉ định, và trả về giá trị đã định nghĩa. Bất kỳ sai lệch nào đều gây ra test thất bại.

Lệnh $this->app->instance() đăng ký mock vào service container của Laravel. Khi PaymentGateway yêu cầu một instance của StripeClient thông qua dependency injection, container cung cấp mock thay vì implementation thực. Cơ chế này dựa trên nguyên tắc đảo ngược phụ thuộc (Dependency Inversion) và là yếu tố cốt lõi của khả năng kiểm thử trong các ứng dụng Laravel được thiết kế tốt. Để hiểu sâu hơn về Service Container và Dependency Injection trong Laravel, có thể tham khảo module phỏng vấn chuyên đề.

Sự khác biệt giữa số tiền truyền vào processCharge (50.00 dollar) và số truyền vào charge (5000 cent) cho thấy một logic chuyển đổi trong PaymentGateway. Test xác thực ngầm sự chuyển đổi này, phát hiện bất kỳ regression nào trong phép tính mà không cần kiểm tra trực tiếp code của class.

Chỉ mock tại ranh giới hệ thống

Một sai lầm phổ biến là mock quá nhiều, dẫn đến các test không còn phản ánh hành vi thực tế của hệ thống. Nguyên tắc chính: chỉ mock các dependency tại ranh giới hệ thống (API bên ngoài, dịch vụ thanh toán, email gateway). Các lớp nội bộ như service và repository nên được kiểm thử với implementation thực của chúng để đảm bảo tính toàn vẹn của luồng dữ liệu.

Sẵn sàng chinh phục phỏng vấn Laravel?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Kiểm Thử Kiến Trúc Với Pest Preset

Pest giới thiệu một tính năng độc đáo trong hệ sinh thái PHP: architecture testing. Các test này xác minh rằng mã nguồn tuân thủ các quy ước cấu trúc do đội ngũ đặt ra, mà không cần thực thi logic ứng dụng. Các vi phạm được phát hiện tĩnh, giống như một linter nâng cao.

tests/Architecture/ArchitectureTest.phpphp
arch('controllers do not use Eloquent directly')
    ->expect('App\Http\Controllers')
    ->not->toUse('Illuminate\Database\Eloquent');

arch('services are final classes')
    ->expect('App\Services')
    ->toBeFinal();

arch('no debugging functions in production code')
    ->expect(['dd', 'dump', 'var_dump', 'ray'])
    ->not->toBeUsed();

Test đầu tiên áp đặt sự tách biệt kiến trúc nghiêm ngặt: các controller không được thao tác Eloquent trực tiếp, buộc phải sử dụng lớp service hoặc repository. Ràng buộc này ngăn chặn việc tích lũy logic nghiệp vụ trong controller — một anti-pattern phổ biến trong các ứng dụng Laravel thiếu cấu trúc. Test thứ hai đảm bảo các class service được khai báo final, ngăn chặn việc kế thừa không kiểm soát. Test thứ ba phát hiện các hàm debug bị bỏ quên trong code production.

Pest cũng cung cấp các preset kiến trúc được cấu hình sẵn, bao quát các quy ước chuẩn của Laravel.

tests/Architecture/LaravelPresetTest.phpphp
arch()->preset()->laravel();
arch()->preset()->security();
arch()->preset()->php();

Preset laravel() kiểm tra rằng controller kế thừa đúng class cơ sở, model nằm trong namespace phù hợp và các quy ước đặt tên được tuân thủ. Preset security() phát hiện việc sử dụng các hàm nguy hiểm như eval(), exec() hoặc shell_exec(). Preset php() áp dụng các best practice chung của ngôn ngữ PHP.

Trong phỏng vấn, kiến thức về architecture testing phân biệt rõ giữa ứng viên có tầm nhìn toàn diện về chất lượng phần mềm và những người chỉ dừng lại ở mức feature test. Các test này mã hóa các quyết định kiến trúc của đội ngũ và tự động hóa việc kiểm tra trong pipeline CI/CD.

Mutation Testing

Code coverage đo lường những dòng code nào được thực thi trong quá trình test, nhưng không đánh giá được chất lượng của các assertion. Mutation testing lấp đầy khoảng trống này bằng cách sửa đổi mã nguồn một cách có hệ thống (thay thế toán tử, xóa điều kiện, thay đổi giá trị trả về) và kiểm tra xem các test có phát hiện được từng thay đổi hay không. Một test vẫn pass dù có mutation là một test chưa đủ chính xác.

Pest tích hợp sẵn mutation testing, giúp thực hành này trở nên dễ tiếp cận mà không cần cấu hình thêm.

bash
# Run mutation testing on a specific class
php artisan test --mutate --class=App\\Services\\PriceCalculator

Lệnh này phân tích class mục tiêu, tạo các mutant và chạy suite test cho từng mutant. Báo cáo chỉ ra mutation score: phần trăm mutant được phát hiện bởi các test hiện có.

Ví dụ sau minh họa sự khác biệt giữa một test có coverage cao nhưng mutation score thấp và một test thực sự vững chắc.

php
// Example: this test has high coverage but low mutation score
it('calculates shipping cost', function () {
    $cost = calculateShipping(weight: 5.0, zone: 'domestic');

    // Only checks that the result is numeric
    expect($cost)->toBeFloat();
});

// Improved: catches mutations by asserting the exact value
it('calculates domestic shipping for 5kg package', function () {
    $cost = calculateShipping(weight: 5.0, zone: 'domestic');

    // Exact assertion catches operator and value mutations
    expect($cost)->toBe(12.50);
});

Test đầu tiên vẫn pass ngay cả khi công thức tính toán bị thay đổi hoàn toàn: bất kỳ số thực nào cũng thỏa mãn assertion toBeFloat(). Test thứ hai áp đặt giá trị chính xác mong đợi, phát hiện mọi mutation trong logic tính toán. Sự khác biệt giữa assertion rộng và assertion chính xác là khái niệm cơ bản mà nhà tuyển dụng thường xuyên đánh giá.

Mutation score từ 90% trở lên cho thấy một suite test thực sự đáng tin cậy, có khả năng phát hiện các regression tinh vi mà coverage 100% về số dòng không thể bắt được.

Mẫu Kiểm Thử Database và Factory

Các buổi phỏng vấn kỹ thuật Laravel thường đưa ra các bài tập kiểm thử về các kịch bản thực tế: xuất bản bài viết, xác thực API, validation form. Ví dụ sau bao quát các trường hợp sử dụng phổ biến này.

tests/Feature/ArticlePublishingTest.phpphp
use App\Models\Article;
use App\Models\User;

it('publishes a draft article and updates the timestamp', function () {
    $author = User::factory()->create(['role' => 'editor']);

    $article = Article::factory()
        ->for($author, 'author')
        ->draft()
        ->create(['title' => 'Testing Best Practices']);

    $this->actingAs($author)
        ->patchJson("/api/articles/{$article->id}/publish")
        ->assertOk()
        ->assertJsonPath('data.status', 'published');

    $article->refresh();

    expect($article->status)->toBe('published')
        ->and($article->published_at)->not->toBeNull()
        ->and($article->published_at->isToday())->toBeTrue();
});

Test này xác thực một workflow xuất bản hoàn chỉnh. Factory draft() tạo một bài viết ở trạng thái nháp, mô phỏng ngữ cảnh ban đầu. Assertion assertJsonPath kiểm tra một giá trị chính xác trong response JSON mà không áp đặt toàn bộ cấu trúc. Lệnh refresh() tải lại model từ cơ sở dữ liệu, đảm bảo các assertion được thực hiện trên trạng thái đã persist chứ không phải cache cục bộ.

Chuỗi assertion Pest với ->and() cho phép kiểm tra nhiều thuộc tính trong một biểu thức fluent duy nhất, cải thiện độ dễ đọc của test. Kiểm tra isToday() tận dụng khả năng của Carbon tích hợp trong Laravel để xác thực rằng timestamp xuất bản là ngày hiện tại.

Kiểm thử song song với Pest

Pest hỗ trợ chạy test song song thông qua flag --parallel, giúp giảm đáng kể thời gian thực thi cho các suite test lớn. Khi sử dụng parallel testing, mỗi process sẽ có cơ sở dữ liệu riêng biệt. Cần đảm bảo rằng các test không chia sẻ trạng thái toàn cục như file trên disk hoặc cache chung. Trait RefreshDatabase tương thích hoàn toàn với chế độ parallel.

Câu Hỏi Phỏng Vấn Kỹ Thuật Về Laravel Testing

Các câu hỏi về kiểm thử trong phỏng vấn Laravel đánh giá sự hiểu biết về cơ chế bên dưới, không chỉ là việc ghi nhớ cú pháp. Dưới đây là các chủ đề thường được hỏi nhất. Để luyện tập thêm, có thể tham khảo các câu hỏi phỏng vấn Laravel và PHP trên SharpSkill.

Sự khác biệt giữa RefreshDatabase và DatabaseMigrations là gì?

Trait RefreshDatabase sử dụng transaction cơ sở dữ liệu để hoàn tác các thay đổi sau mỗi test, nhanh hơn đáng kể so với DatabaseMigrations. DatabaseMigrations chạy toàn bộ migration trước mỗi test và truncate các bảng sau đó, chậm hơn nhưng cần thiết trong một số trường hợp khi transaction không đủ (ví dụ: test liên quan đến nhiều kết nối cơ sở dữ liệu).

Tại sao nên sử dụng factory thay vì insert thủ công?

Factory đóng gói việc tạo đối tượng test với các giá trị mặc định nhất quán. Chúng cho phép chỉ định các thuộc tính liên quan đến test hiện tại, giúp ý định của test trở nên rõ ràng. Factory tự động quản lý các quan hệ giữa model thông qua phương thức for()has(), loại bỏ code tạo dữ liệu lặp lại.

Làm thế nào để test middleware mà không test toàn bộ controller?

Laravel cho phép khởi tạo middleware trực tiếp và gọi phương thức handle() với một request được tạo sẵn. Cách tiếp cận này cô lập logic middleware khỏi controller. Ngoài ra, một feature test nhắm đích với assertion về HTTP status cũng có thể xác minh hành vi middleware trong ngữ cảnh.

Khi nào nên dùng Mockery thay vì facade fake?

Các facade fake (Mail::fake(), Queue::fake()) đủ dùng cho các service tích hợp sẵn của Laravel. Mockery cần thiết cho các dịch vụ bên thứ ba (API client, SDK bên ngoài) không phải facade. Quy tắc chung: sử dụng facade fake khi có sẵn, Mockery cho phần còn lại.

Architecture test xác thực điều gì mà test thông thường không bao quát?

Architecture test kiểm tra cấu trúc và dependency của code mà không thực thi nó. Chúng phát hiện các vi phạm quy ước (controller sử dụng Eloquent trực tiếp, hàm debug bị bỏ quên, service không được khai báo final) mà feature test không thể bắt được vì code vẫn hoạt động đúng dù có vi phạm kiến trúc.

Giải thích mutation score thấp khi coverage cao?

Mutation score thấp với coverage cao có nghĩa là các test thực thi code nhưng không kiểm tra kết quả với độ chính xác đầy đủ. Giải pháp là thay thế các assertion rộng (toBeFloat, toBeArray) bằng assertion chính xác (toBe(12.50), toHaveCount(3)) để phát hiện các thay đổi trong logic nghiệp vụ.

Kiểm Thử HTTP

Kiểm thử xác thực API là một chủ đề thường xuyên xuất hiện trong phỏng vấn Laravel. Nhóm test sau bao quát ba kịch bản cơ bản của mọi API có xác thực: từ chối request chưa xác thực, trả về dữ liệu cho người dùng đã đăng nhập, và validation các trường bắt buộc.

tests/Feature/ApiAuthenticationTest.phpphp
use App\Models\User;

describe('API Authentication', function () {
    it('rejects unauthenticated requests with 401', function () {
        $this->getJson('/api/profile')
            ->assertUnauthorized();
    });

    it('returns the authenticated user profile', function () {
        $user = User::factory()->create([
            'name' => 'John Doe',
            'email' => 'john@example.com',
        ]);

        $this->actingAs($user)
            ->getJson('/api/profile')
            ->assertOk()
            ->assertJson([
                'data' => [
                    'name' => 'John Doe',
                    'email' => 'john@example.com',
                ],
            ]);
    });

    it('validates required fields on registration', function () {
        $this->postJson('/api/register', [])
            ->assertUnprocessable()
            ->assertJsonValidationErrors(['name', 'email', 'password']);
    });
});

Assertion assertUnauthorized() kiểm tra status 401, trong khi assertUnprocessable() tương ứng với status 422 chuẩn cho lỗi validation. Việc sử dụng assertJsonValidationErrors xác thực rằng lỗi validation được định dạng đúng và liên kết với các trường tương ứng — pattern không thể thiếu cho các API được sử dụng bởi client frontend hiển thị thông báo lỗi dưới mỗi trường form.

Kết Luận

Kiểm thử Laravel với Pest trong năm 2026 không chỉ là một kỹ năng kỹ thuật bổ sung mà còn là trụ cột của uy tín chuyên môn của lập trình viên PHP. Khả năng viết test expressive, mock đúng các dependency bên ngoài và duy trì các quy ước kiến trúc tự động là yếu tố phân biệt giữa ứng viên senior và ứng viên trung cấp.

Các điểm then chốt cần ghi nhớ cho phỏng vấn kỹ thuật:

  • Cấu hình Pest: file tests/Pest.php tập trung các trait và class cơ sở, tách biệt rõ ràng unit test và feature test
  • Feature test: sự kết hợp postJson / assertStatus / expect bao quát toàn bộ chuỗi xử lý của endpoint
  • Mocking facade: Mail::fake(), Queue::fake() và các assertion đi kèm là pattern chuẩn để kiểm thử các quy trình bất đồng bộ
  • Mockery: cho các dịch vụ bên thứ ba, inject mock thông qua service container tuân thủ nguyên tắc đảo ngược phụ thuộc
  • Architecture test: mã hóa các quyết định cấu trúc của đội ngũ và tự động kiểm tra trong pipeline CI/CD
  • Mutation testing: mutation score tiết lộ chất lượng thực sự của assertion, vượt xa coverage số dòng đơn thuần
  • Factory và assertion: thành thạo factory Laravel và assertion JSON chi tiết giúp tăng tốc việc viết test bền vững

Trong quá trình tuyển dụng Laravel, việc thể hiện cách tiếp cận kiểm thử có cấu trúc biến bài tập kỹ thuật thành cơ hội trưng bày năng lực chuyên môn. Mỗi test được viết tốt thể hiện sự hiểu biết sâu về framework và tính kỷ luật cần thiết để đảm bảo độ tin cậy của code trong môi trường production.

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Thẻ

#laravel
#testing
#pest
#php
#mocking
#best-practices
#interview

Chia sẻ

Bài viết liên quan