Một số thủ thuật Unit Test trong Laravel

Giới thiệu UT là kỹ thuật kiểm nghiệm các hoạt động của mọi chi tiết trong code với một quy trình tách biệt với quy trình phát triển phần mềm, giúp phát hiện sai sót kịp thời. UT còn có thể giúp phát hiện các vấn đề tiềm ẩn và các lỗi thời gian thực ngay cả trước khi chuyên viên kiểm định chất lượng (QA - Quality Assurance) tìm ra, thậm chí có thể sửa lỗi ngay từ ý tưởng thiết kế.

UT là các đoạn mã có cấu trúc giống như các đối tượng được xây dựng để kiểm tra từng bộ phận trong hệ thống. Mỗi UT sẽ gửi đi một thông điệp và kiểm tra câu trả lời nhận được đúng hay không, bao gồm:

Các kết quả trả về mong muốn Các lỗi ngoại lệ mong muốn Các đoạn mã UT hoạt động liên tục hoặc định kỳ để thăm dò và phát hiện các lỗi kỹ thuật trong suốt quá trình phát triển, do đó UT còn được gọi là kỹ thuật kiểm nghiệm tự động. Trong Laravel ta sẽ sử dụng phpunit để làm điều này. Và trong bài viết này tôi sẽ chia sẻ 1 vài thủ thuật để bạn có thể thiết lập Unit test dễ dàng. 1. Mocking: Trong điều kiện lí tưởng, khi bạn viết unit test, mỗi hàm test sẽ chỉ phụ trách một phần chức năng nhất định, và không phụ thuộc lẫn nhau. Điều đó có nghĩa là, nếu ta đã có code test cho phần logic, lấy dữ liệu từ database ra chẳng hạn, thì khi test trên controller, ta không cần phải quan tâm đến chuyện phía database có làm việc đúng hay không. Sử dụng Mockery tạo ra các Mock Object sẽ cho phép ta mô phỏng các chức năng không thuộc phạm vi trách nhiệm của mình, để đảm bảo tính độc lập của test. Khi cần giá trị trả về của 1 function nào đó ta sẽ cần mock class chứa function đó:

<?php

namespace Tests\Unit\Console\Commands;

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Mockery;
use App\Services\ExampleService;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;
    /**
     * @var \Mockery\Mock|Services\ExampleService
     */
    protected $exampleServiceMock;

    public function setUp()
    {
        $this->afterApplicationCreated(function () {
            $this->exampleServiceMock = Mockery::mock(ExampleService::class);
        });

        parent::setUp();
    }

và sử dụng nó:

public function testNormalDataInput()
    {
        $this->exampleServiceMock->shouldReceive('exampleFunction')
            ->once()
            ->andReturn(false);
        $this->app->instance('App\Services\ExampleService', $this->exampleServiceMock);
        ...
    }

Như vậy khi ta sử dụng hàm exampleFunction trong exampleService thì được trả về giá trị mặc định false mà không xử lý bên trong hàm exampleFunction.

2.Fake Request: Khi bạn dùng custom request trong việc validation thì khi unit test việc tạo mới request sẽ dính 1 vấn đề đó là Validate sẽ tự chạy ngay việc tạo request bằng hàm:

app('ExampleRequest');

bởi request chứa đặc tính validate ngay sau resolve:

		$this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {
            $resolved->validate();
        });

Để tránh điều này ta có thể làm như sau:

		$request = new ExampleRequest();
        $request->setContainer($this->app)->setRedirector($this->app->make(Redirector::class));
        $this->app->instance('request', $request);

        $request->headers->set('content-type', 'application/json');
        $request->setJson(new ParameterBag($data));

và khi cần check validate ta chỉ cần gọi:

	$request->validate();

3.Test Command: Để có thể test command artían ta cần thư viện:

use Illuminate\Support\Facades\Artisan;

Và sử dụng một cách dễ dàng:

		Artisan::call('exampleBatch', $dataInput);
        $this->assertContains('message', Artisan::output());

Ta có thể kiểm tra các output message bằng hàm Artisan::output()

Trên đây là một số thủ thuật nhỏ trong Unit Test Laravel, tôi hi vọng nó có thể giúp các bạn trong việc tạo Unit Test dễ dàng hơn.