如何在 PHP 中測試 Trait

程式技術

在使用 Laravel Livewire 的時候,我時常會把 livewire component 中可以重複使用的邏輯或是方法抽出並放在 Trait 中。

Laravel Livewire 官方文件中也建議使用 Trait 來處理經常重複使用的邏輯。詳細可以參考下面兩個連結。

例如我有一個將 Markdown 轉換為 HTML 的方法,因為有很多 livewire component 都會使用到這個方法,所以我將這個方法放到 trait 中。

namespace App\Http\Traits\Livewire;

use Illuminate\Support\Str;

trait MarkdownConverter
{
    public function convertToHtml(string $body): string
    {
        $html = Str::of($body)->markdown([
            'html_input' => 'strip',
        ]);
    }
}

當我想在 livewire component 中使用這個方法時,只要簡單的使用 use 引入即可。

namespace App\Http\Livewire\Comments;

// ...
use App\Http\Traits\Livewire\MarkdownConverter;

use Livewire\Component;

class Comment extends Component
{
    use MarkdownConverter;

    // ...
    
    public function getConvertedBodyProperty(): string
    {
        return $this->convertToHtml($this->body);
    }
    
    // ...
}

Trait 用多了之後也讓我遇到一個問題。

那如果我想測試 trait 中的方法,可以怎麼做呢?

以下的測試範例皆使用 Pest,是一個建構於 PHPUnit 上的測試框架。

在測試中使用 use 引入

我們可以在測試中使用 use 將 Trait 引入,這樣就可以直接使用 Trait 中的方法。

use App\Http\Traits\Livewire\MarkdownConverter;

// 使用 use 引入 trait
uses(MarkdownConverter::class);

it('can convert the markdown content to html', function () {
    $body = '# Header 1'

    // 引入後 trait 就可以在測試中使用 convertToHtml() 方法
    $convertedBody = $this->convertToHtml($body);

    expect($convertedBody)
        ->toContain('<h1>Header 1</h1>')
});

使用匿名類別

使用 PHP 的匿名類別,簡單的建立一個實例,並在實例中使用 use 引入 Trait,在之後的測試中,我們就可以使用實例來呼叫 trait 中的方法。

use App\Http\Traits\Livewire\MarkdownConverter;

it('can block the header tag', function () {
    // 使用匿名類別建立一個引入 trait 的實例
    $trait = new class
    {
        use MarkdownConverter;
    };

    $body = '# Header 1'

    $convertedBody = $trait->convertToHtml($body);

    expect($convertedBody)
        ->toContain('<h1>Header 1</h1>')
});

使用 PHPUnit 的 getObjectForTrait 方法

與剛剛的方法類似,我們可以使用 PHPUnit 提供 getObjectForTrait() 方法來取得引入 trait 後的實例。

use App\Http\Traits\Livewire\MarkdownConverter;

it('can block the header tag', function () {
    // 透過 PHPUnit 的 getObjectForTrait() 方法取得引入 trait 的實例
    $trait = $this->getObjectForTrait(MarkdownConverter::class);

    $body = '# Header 1'

    $convertedBody = $trait->convertToHtml($body);

    expect($convertedBody)
        ->toContain('<h1>Header 1</h1>')
});

參考資料

sharkHead
written by
sharkHead

持續努力中的後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

1 則留言
訪客

太讚了!!

新增留言
編輯留言