LARAVEL TUTORIALS
10 thủ thuật Lavavel giúp bạn code nhanh hơn! Routing trong Laravel, cách tạo Route và sử dung AZ Tạo Middleware trong Laravel đơn giản trong 5 phút Xử lý Authentication và Authorization trong Laravel Event và listener trong Laravel, cách tạo và quản lý cơ bản nhất Tạo broadcast event trong Laravel dễ dàng trong 10 phút Xử lý Form Validation trong Laravel từ A - Z Cách tạo Session và cookie trong Laravel dễ dàng như ăn cháo Top 10 Package Lavavel thường dùng trong dự án Laravel Sử dụng Task trong Laravel đơn giản trong 10 phút. Cách tạo API trong Laravel đơn giản chỉ trong 5 phút Cách tạo job trong Laravel sao cho hiệu quả? Queues trong Laravel, dùng để xử lý các tác vụ mất nhiều thời gian Cache trong Laravel, các loại Cache thường dùng trong Laravel Redis trong Laravel, biết cách sử dung Redis Laravel trong 5 phút Sử dụng Memcache trong Laravel tăng tốc độ truy cập website Unit Test trong Laravel, thực hành tạo testing Laravel A-Z 10 thủ thuật tối ưu quá trình Testing trong Laravel Top 7 thư viện Testing Laravel được dùng nhiều nhất Testbench và Orchestra Testbench trong Laravel, kiểm thử Laravel dễ dàng Cách dùng Browser Testing (Laravel Dusk) trong Laravel Cách tạo test case cho Controller trong Laravel Cách tạo test case cho Model trong Laravel Cách tạo Database Testing trong Laravel Real-time web applications là gì ? Tầm quan trọng trong Laravel Laravel WebSockets, các bước tạo WebSockets trong Laravel Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime Dùng Server-Sent Events trong Laravel để làm ứng dụng realtime Cách dùng Long polling trong Laravel để cải thiện trải nghiệm Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ Cách dùng Event Sourcing trong Laravel Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản Sử dụng Service Container trong Laravel dễ dàng Cách xử lý đa ngôn ngữ trong Laravel dễ dàng Tìm hiểu và sử dụng Service Provider trong Laravel Facades là gì? Cách dùng Facades trong Laravel Cách sử dụng Email Verification trong Laravel Cách dùng URL Generation trong Larevel Cách sử dụng Error Handling trong Laravel Cách dùng Encryption và decryption trong Laravel Cách sử dụng Relationships trong Laravel Bài 01: Laravel là gì? Hướng dẫn cài đặt laravel trên windows Sử dụng Event trong Laravel Một cách quản lý filter trong Laravel
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Cách tạo test case cho Controller trong Laravel

Cách tạo test case cho Controller trong Laravel. Testing các action trong Controller giúp chúng ta đảm bảo tính đúng đắn của chúng và đối chiếu kết quả với kết quả mong đợi. Chúng ta sẽ cùng nhau tìm hiểu các nội dung chính để tạo test case cho Controller trong Laravel .

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Cài đặt các test case cho controller Laravel

Bạn cần cài đặt các gói phụ thuộc để thực hiện testing trong Laravel, bao gồm PHPUnit và Laravel Dusk (nếu muốn thực hiện browser testing).

PHPUnit

PHPUnit là một framework để thực hiện testing cho PHP. Để cài đặt PHPUnit, bạn có thể sử dụng Composer bằng cách thêm dòng sau vào file composer.json:

"require-dev": {
    "phpunit/phpunit": "^9.5"
}

Sau đó chạy lệnh composer update để cập nhật các gói phụ thuộc.

Bài viết này được đăng tại [free tuts .net]

Laravel Dusk

Laravel Dusk là một gói phụ thuộc để thực hiện browser testing trong Laravel. Để cài đặt Laravel Dusk, bạn có thể sử dụng Composer bằng cách thêm dòng sau vào file composer.json:

"require-dev": {
    "laravel/dusk": "^5.0"
}

Sau đó chạy lệnh composer update để cập nhật các gói phụ thuộc.

Tạo một test case cho controller Laravel

Để tạo một test case mới cho Controller trong Laravel , bạn có thể sử dụng lệnh php artisan make:test trong terminal hoặc tạo một class test case thủ công.

Bước 1: Sử dụng lệnh php artisan make:test

Mở terminal và nhập lệnh php artisan make:test TenTestCase --unit hoặc php artisan make:test TenTestCase --feature tùy thuộc vào loại test case mà bạn muốn tạo.

Ví dụ:

php artisan make: test UserControllerTest --feature

Lệnh này sẽ tạo ra một file UserControllerTest.php trong thư mục tests/Feature hoặc tests/Unit tùy thuộc vào loại test case mà bạn đã chọn.

Bước 2: Tạo một class test case thủ công

Tạo một class mới trong thư mục tests/Feature hoặc tests/Unit.

Ví dụ:

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserControllerTest extends TestCase
{
    //freetuts.net
}

Thêm các phương thức test vào class này để kiểm tra các action trong Laravel Controller.

Ví dụ:

public function test_user_can_register()
{
$response = $this->post('/register', [
'name' => 'John Doe',
'email' => 'johndoe@example.com',
'password' => 'password',
'password_confirmation' => 'password'
]);
}

Trong phương thức test này, chúng ta sử dụng phương thức $this->post() để gửi một POST request đến endpoint /register với các thông tin người dùng. Sau đó, chúng ta sử dụng các phương thức assertRedirect(), assertAuthenticated() assertDatabaseHas() để kiểm tra kết quả trả về của request.

Viết các test case cho controller Laravel

Test case hiển thị trang chủ (index)

public function test_index()
{
    $response = $this->get(route('posts.index'));

    $response->assertStatus(200);
    $response->assertViewIs('posts.index');
    $response->assertViewHas('posts');
}

Test case hiển thị trang tạo mới bài viết (create)

public function test_create()
{
    $response = $this->get(route('posts.create'));

    $response->assertStatus(200);
    $response->assertViewIs('posts.create');
}

Test case lưu bài viết mới (store)

public function test_store()
{
    $data = [
        'title' => 'Test Title',
        'content' => 'Test Content'
    ];

    $response = $this->post(route('posts.store'), $data);

    $response->assertRedirect(route('posts.index'));
    $this->assertDatabaseHas('posts', $data);
}

Test case hiển thị chi tiết bài viết (show)

public function test_show()
{
    $post = factory(Post::class)->create();

    $response = $this->get(route('posts.show', $post->id));

    $response->assertStatus(200);
    $response->assertViewIs('posts.show');
    $response->assertViewHas('post', $post);
}

Test case hiển thị trang chỉnh sửa bài viết (edit)

public function test_edit()
{
    $post = factory(Post::class)->create();

    $response = $this->get(route('posts.edit', $post->id));

    $response->assertStatus(200);
    $response->assertViewIs('posts.edit');
    $response->assertViewHas('post', $post);
}

Test case cập nhật bài viết (update)

public function test_update()
{
    $post = factory(Post::class)->create();

    $data = [
        'title' => 'Updated Title',
        'content' => 'Updated Content'
    ];

    $response = $this->put(route('posts.update', $post->id), $data);

    $response->assertRedirect(route('posts.index'));
    $post->refresh();
    $this->assertEquals('Updated Title', $post->title);
    $this->assertEquals('Updated Content', $post->content);
}

Test case xóa bài viết (destroy)

public function test_destroy()
{
    $post = factory(Post::class)->create();

    $response = $this->delete(route('posts.destroy', $post->id));

    $response->assertRedirect(route('posts.index'));
    $this->assertDeleted('posts', $post->toArray());
}

Sử dụng HTTP tests cho controller Laravel

Để sử dụng HTTP tests trong Laravel Controller, ta sử dụng các phương thức HTTP như get, post, put, delete... của Laravel Testing Framework để tạo các HTTP request tương ứng với các action của Controller.

Ví dụ, để test store trong PostController, ta có thể viết test case như sau:

public function test_store()
{
    $data = [
        'title' => 'Test Title',
        'content' => 'Test Content'
    ];

    $response = $this->post(route('posts.store'), $data);

    $response->assertStatus(302); // Kiểm tra status code của response
    $response->assertRedirect(route('posts.index')); // Kiểm tra redirect đến trang danh sách bài viết
    $this->assertDatabaseHas('posts', $data); // Kiểm tra bản ghi đã được lưu vào database
}

Trong đó, $this->post là phương thức của Laravel Testing Framework để tạo một HTTP POST request, và $response là response trả về từ server khi request được thực hiện. Ta sử dụng phương thức assertStatus để kiểm tra status code của response, assertRedirect để kiểm tra redirect đến đúng trang cần thiết và assertDatabaseHas để kiểm tra bản ghi đã được lưu vào database.

Tương tự, để test khác, ta có thể sử dụng các phương thức HTTP tương ứng và kiểm tra các response trả về để đảm bảo hoạt động đúng trong Controller.

Sử dụng Mocks cho controller Laravel

Để sử dụng Mocks Controller trong Laravel, ta sử dụng các thư viện Mocking của PHP như PHPUnit Mock Objects hoặc Mockery để tạo ra các đối tượng giả tạo (mock objects) thay thế cho các đối tượng thực sự (real objects) mà Controller sử dụng.

Ví dụ, để test store trong PostController mà phụ thuộc vào một đối tượng PostRepository, ta có thể sử dụng Mocks để tạo ra một đối tượng PostRepository giả tạo để kiểm soát kết quả trả về từ phương thức create của đối tượng này. Ví dụ code test case có thể như sau:

public function test_store()
{
    $postData = [
        'title' => 'Test Title',
        'content' => 'Test Content'
    ];

    // Tạo một mock object cho đối tượng PostRepository
    $mockPostRepository = Mockery::mock(PostRepository::class);
    // Đặt kết quả trả về của phương thức create của mock object này là true
    $mockPostRepository->shouldReceive('create')->once()->with($postData)->andReturn(true);

    // Inject mock object vào trong Controller thông qua Dependency Injection
    $postController = new PostController($mockPostRepository);

    // Gọi action store với dữ liệu $postData
    $response = $postController->store($postData);

    // Kiểm tra kết quả trả về từ action store
    $this->assertInstanceOf(RedirectResponse::class, $response);
    $this->assertEquals(route('posts.index'), $response->getTargetUrl());
}

Trong đó, $mockPostRepository là đối tượng mock giả tạo cho đối tượng PostRepository, ta sử dụng phương thức shouldReceive để đặt kết quả trả về của phương thức create của đối tượng này là true. Sau đó, ta inject mock object này vào trong Controller thông qua Dependency Injection. Cuối cùng, ta gọi store với dữ liệu $postData và kiểm tra kết quả trả về từ action này.

Tương tự, ta có thể sử dụng Mocks để kiểm soát các đối tượng khác mà Controller phụ thuộc vào và kiểm tra các kết quả trả về từ các action trong Controller.

Sử dụng Browser tests cho controller Laravel

Để sử dụng Browser tests cho các action trong Laravel Controller, ta sử dụng Laravel Dusk - một công cụ testing browser automation của Laravel. Dusk cho phép ta tạo các test case để tự động hoá việc điều khiển trình duyệt và kiểm tra các hành vi và kết quả trả về từ các trang web.

Ví dụ, để test store trong PostController bằng Browser tests, ta có thể viết test case như sau:

public function test_store()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/posts/create')
                ->type('title', 'Test Title')
                ->type('content', 'Test Content')
                ->press('Submit')
                ->assertPathIs('/posts')
                ->assertSee('Test Title')
                ->assertSee('Test Content');
    });
}

Trong đó, $this->browse là phương thức của Laravel Dusk để tạo một session mới với trình duyệt và thực hiện các hành động trên trang web. Trong test case này, ta dùng $browser->visit để mở trang tạo bài viết mới, sau đó dùng $browser->type để điền dữ liệu vào các trường title và content, và $browser->press để bấm nút Submit. Cuối cùng, ta dùng các phương thức assertPathIsassertSee để kiểm tra kết quả trả về của store.

Tương tự, ta có thể sử dụng Browser tests để kiểm tra các action khác của Controller và các kết quả trả về từ các trang web.

Chạy các test case cho controller Laravel

Để chạy các test case Controller trong Laravel , ta có thể sử dụng một trong các bộ framework testing cho PHP như PHPUnit hoặc Codeception.

Ví dụ, để chạy các test case cho PostController bằng PHPUnit, ta có thể viết các test case trong file tests/Feature/PostControllerTest.php, và sử dụng lệnh php artisan test để chạy toàn bộ test case trong thư mục tests:

<?php

namespace Tests\Feature;

use App\Models\Post;
use App\Repositories\PostRepository;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PostControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_index()
    {
        $response = $this->get(route('posts.index'));

        $response->assertStatus(200);
    }

    public function test_create()
    {
        $response = $this->get(route('posts.create'));

        $response->assertStatus(200);
    }

    public function test_store()
    {
        $postData = [
            'title' => 'Test Title',
            'content' => 'Test Content'
        ];

        $mockPostRepository = $this->mock(PostRepository::class);
        $mockPostRepository->shouldReceive('create')->once()->with($postData)->andReturn(true);

        $response = $this->post(route('posts.store'), $postData);

        $response->assertRedirect(route('posts.index'));
    }

    public function test_show()
    {
        $post = Post::factory()->create();

        $response = $this->get(route('posts.show', $post->id));

        $response->assertStatus(200);
    }

    public function test_edit()
    {
        $post = Post::factory()->create();

        $response = $this->get(route('posts.edit', $post->id));

        $response->assertStatus(200);
    }

    public function test_update()
    {
        $post = Post::factory()->create();
        $postData = [
            'title' => 'Updated Title',
            'content' => 'Updated Content'
        ];

        $mockPostRepository = $this->mock(PostRepository::class);
        $mockPostRepository->shouldReceive('update')->once()->with($post->id, $postData)->andReturn(true);

        $response = $this->put(route('posts.update', $post->id), $postData);

        $response->assertRedirect(route('posts.index'));
    }

    public function test_destroy()
    {
        $post = Post::factory()->create();

        $mockPostRepository = $this->mock(PostRepository::class);
        $mockPostRepository->shouldReceive('delete')->once()->with($post->id)->andReturn(true);

        $response = $this->delete(route('posts.destroy', $post->id));

        $response->assertRedirect(route('posts.index'));
    }
}

Trong đó, các test case được đặt trong các phương thức test_ và sử dụng các phương thức của Laravel Test để thực hiện các action và kiểm tra kết quả trả về. Trong ví dụ này, ta sử dụng mock để tạo các đối tượng giả tạo cho các đối tượng phụ thuộc của Controller.

Để chạy các test case trong file này, ta chỉ cần sử dụng lệnh php artisan test trong terminal. Nếu muốn chạy riêng một test case cụ thể, ta có thể sử dụng option --filter để chỉ định tên của test case. Ví dụ, để chạy test case test_store trong PostControllerTest, ta có thể sử dụng lệnh sau:

php artisan test --filter test_store

Ngoài ra, để kiểm tra coverage của các test case, ta có thể sử dụng thêm option --coverage-html để tạo ra báo cáo về code coverage của các test case trong project.

Ví dụ:

php artisan test --coverage-html coverage-report

Sau khi chạy các test case, ta có thể xem kết quả trên terminal hoặc truy cập vào file HTML tạo ra bởi option --coverage-html để xem báo cáo về code coverage của các test case.

Một số câu hỏi về cách tạo test case cho Controller trong Laravel

1. Tại sao lại cần phải tạo test case cho các action trong Controller?

  • Việc tạo test case cho các action trong Controller giúp đảm bảo tính ổn định và độ chính xác của ứng dụng.
  • Các test case giúp định nghĩa và mô tả rõ các hành vi và kết quả của các action trong Controller.
  • Test case cũng giúp cho việc maintain và upgrade ứng dụng trở nên dễ dàng và an toàn hơn.

2. Sử dụng kỹ thuật nào để tạo test case cho các action trong Controller?

Có nhiều kỹ thuật để tạo test case cho các action trong Controller, bao gồm:

  • HTTP tests: kiểm tra kết quả trả về của các request tới các action trong Controller.
  • Mocks: giả lập các đối tượng (objects) phụ thuộc và kiểm tra xem action có đúng kết quả hay không.
  • Browser tests: kiểm tra các hành vi của người dùng khi tương tác với các action trong Controller.

3. Làm thế nào để chạy các test case đã tạo?

Để chạy các test case đã tạo, ta có thể sử dụng lệnh php artisan test để chạy tất cả các test case trong project. Để chạy một test case cụ thể, ta có thể sử dụng option --filter để chỉ định tên của test case. Ta cũng có thể sử dụng option --coverage-html để tạo ra báo cáo về code coverage của các test case trong project.

4. Làm thế nào để đảm bảo tính ổn định và độ chính xác của các test case?

Để đảm bảo tính ổn định và độ chính xác của các test case, ta cần phải chú ý đến các yếu tố sau:

  • Tạo test case đầy đủ và chi tiết, đảm bảo các tình huống có thể xảy ra đã được kiểm tra.
  • Đảm bảo rằng các test case không phụ thuộc vào các tài nguyên bên ngoài như cơ sở dữ liệu hay file system.
  • Sử dụng các kỹ thuật giả lập (mocking) để giảm thiểu sự phụ thuộc vào các đối tượng (objects) khác.
  • Thực hiện các test case trên môi trường giống với môi trường sản phẩm để đảm bảo tính chính xác của kết quả kiểm tra.

Kết bài viết

Trong bài viết này, chúng ta đã tìm hiểu về cách tạo test case cho các action trong Laravel Controller. Chúng ta đã thực hiện các test case bằng HTTP tests, Mocks và Browser tests. Các kỹ thuật này đều rất hữu ích trong việc tạo ra các test case chính xác và đáng tin cậy để đảm bảo rằng các action trong Controller của chúng ta hoạt động đúng như mong đợi.

Việc tạo ra các test case cho các action trong Laravel Controller sẽ giúp chúng ta giảm thiểu các lỗi và tăng tính ổn định của ứng dụng của chúng ta. Ngoài ra, việc tạo test case cũng giúp cho việc maintain và upgrade ứng dụng trở nên dễ dàng và an toàn hơn.

Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về cách tạo test case cho các action trong Laravel Controller và áp dụng thành công vào dự án của bạn.

Cùng chuyên mục:

Cách sử dụng Relationships trong Laravel

Cách sử dụng Relationships trong Laravel

Cách dùng Encryption và decryption trong Laravel

Cách dùng Encryption và decryption trong Laravel

Cách sử dụng Error Handling trong Laravel

Cách sử dụng Error Handling trong Laravel

Cách dùng URL Generation trong Larevel

Cách dùng URL Generation trong Larevel

Cách sử dụng Email Verification trong Laravel

Cách sử dụng Email Verification trong Laravel

Facades là gì? Cách dùng Facades trong Laravel

Facades là gì? Cách dùng Facades trong Laravel

Tìm hiểu và sử dụng Service Provider trong Laravel

Tìm hiểu và sử dụng Service Provider trong Laravel

Sử dụng Service Container trong Laravel dễ dàng

Sử dụng Service Container trong Laravel dễ dàng

Cách xử lý đa ngôn ngữ trong Laravel dễ dàng

Cách xử lý đa ngôn ngữ trong Laravel dễ dàng

Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản

Cách sử dụng CQRS trong Laravel từ A đến Z đơn giản

Cách dùng Event Sourcing trong Laravel

Cách dùng Event Sourcing trong Laravel

Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel

Task Scheduling là gì? Cấu hình Task Scheduling trong Laravel

Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ

Cách dùng Queue trong laravel để tạo tác vụ bất đồng bộ

Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản

Cách tích hợp Vue.js vào Laravel và làm một ứng dụng căn bản

Cách dùng Long polling trong Laravel để cải thiện trải nghiệm

Cách dùng Long polling trong Laravel để cải thiện trải nghiệm

Dùng Server-Sent Events trong Laravel để làm ứng dụng realtime

Dùng Server-Sent Events trong Laravel để làm ứng dụng realtime

Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime

Cách dùng Socket.io trong Laravel để tạo ứng dụng realtime

Laravel WebSockets, các bước tạo WebSockets trong Laravel

Laravel WebSockets, các bước tạo WebSockets trong Laravel

Real-time web applications là gì ? Tầm quan trọng  trong Laravel

Real-time web applications là gì ? Tầm quan trọng trong Laravel

Cách tạo Database Testing trong Laravel

Cách tạo Database Testing trong Laravel

Top