跳到內容

Console 測試

簡介

除了簡化 HTTP 測試外,Laravel 還提供了一個簡單的 API 來測試應用程式的自訂命令列指令

成功 / 失敗預期

首先,讓我們探索如何對 Artisan 命令的退出代碼進行斷言。為了完成此操作,我們將使用 artisan 方法從我們的測試中調用 Artisan 命令。然後,我們將使用 assertExitCode 方法來斷言命令以給定的退出代碼完成

1test('console command', function () {
2 $this->artisan('inspire')->assertExitCode(0);
3});
1/**
2 * Test a console command.
3 */
4public function test_console_command(): void
5{
6 $this->artisan('inspire')->assertExitCode(0);
7}

您可以使用 assertNotExitCode 方法來斷言命令沒有以給定的退出代碼退出

1$this->artisan('inspire')->assertNotExitCode(1);

當然,所有終端命令通常在成功時以狀態碼 0 退出,而在不成功時以非零退出代碼退出。因此,為了方便起見,您可以利用 assertSuccessfulassertFailed 斷言來斷言給定的命令是否以成功的退出代碼退出

1$this->artisan('inspire')->assertSuccessful();
2 
3$this->artisan('inspire')->assertFailed();

輸入 / 輸出預期

Laravel 允許您使用 expectsQuestion 方法輕鬆「模擬」使用者對控制台命令的輸入。此外,您可以使用 assertExitCodeexpectsOutput 方法指定您期望控制台命令輸出的退出代碼和文本。例如,考慮以下控制台命令

1Artisan::command('question', function () {
2 $name = $this->ask('What is your name?');
3 
4 $language = $this->choice('Which language do you prefer?', [
5 'PHP',
6 'Ruby',
7 'Python',
8 ]);
9 
10 $this->line('Your name is '.$name.' and you prefer '.$language.'.');
11});

您可以使用以下測試來測試此命令

1test('console command', function () {
2 $this->artisan('question')
3 ->expectsQuestion('What is your name?', 'Taylor Otwell')
4 ->expectsQuestion('Which language do you prefer?', 'PHP')
5 ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
6 ->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')
7 ->assertExitCode(0);
8});
1/**
2 * Test a console command.
3 */
4public function test_console_command(): void
5{
6 $this->artisan('question')
7 ->expectsQuestion('What is your name?', 'Taylor Otwell')
8 ->expectsQuestion('Which language do you prefer?', 'PHP')
9 ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
10 ->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')
11 ->assertExitCode(0);
12}

如果您正在使用 Laravel Prompts 提供的 searchmultisearch 函數,則可以使用 expectsSearch 斷言來模擬使用者的輸入、搜尋結果和選擇

1test('console command', function () {
2 $this->artisan('example')
3 ->expectsSearch('What is your name?', search: 'Tay', answers: [
4 'Taylor Otwell',
5 'Taylor Swift',
6 'Darian Taylor'
7 ], answer: 'Taylor Otwell')
8 ->assertExitCode(0);
9});
1/**
2 * Test a console command.
3 */
4public function test_console_command(): void
5{
6 $this->artisan('example')
7 ->expectsSearch('What is your name?', search: 'Tay', answers: [
8 'Taylor Otwell',
9 'Taylor Swift',
10 'Darian Taylor'
11 ], answer: 'Taylor Otwell')
12 ->assertExitCode(0);
13}

您也可以使用 doesntExpectOutput 方法斷言控制台命令未產生任何輸出

1test('console command', function () {
2 $this->artisan('example')
3 ->doesntExpectOutput()
4 ->assertExitCode(0);
5});
1/**
2 * Test a console command.
3 */
4public function test_console_command(): void
5{
6 $this->artisan('example')
7 ->doesntExpectOutput()
8 ->assertExitCode(0);
9}

expectsOutputToContaindoesntExpectOutputToContain 方法可用於針對輸出的一部分進行斷言

1test('console command', function () {
2 $this->artisan('example')
3 ->expectsOutputToContain('Taylor')
4 ->assertExitCode(0);
5});
1/**
2 * Test a console command.
3 */
4public function test_console_command(): void
5{
6 $this->artisan('example')
7 ->expectsOutputToContain('Taylor')
8 ->assertExitCode(0);
9}

確認預期

當編寫需要以「是」或「否」答案形式進行確認的命令時,您可以使用 expectsConfirmation 方法

1$this->artisan('module:import')
2 ->expectsConfirmation('Do you really wish to run this command?', 'no')
3 ->assertExitCode(1);

表格預期

如果您的命令使用 Artisan 的 table 方法顯示資訊表格,則為整個表格編寫輸出預期可能會很麻煩。相反,您可以使用 expectsTable 方法。此方法接受表格的標頭作為其第一個參數,表格的資料作為其第二個參數

1$this->artisan('users:all')
2 ->expectsTable([
3 'ID',
4 'Email',
5 ], [
8 ]);

Console 事件

預設情況下,在執行應用程式的測試時,不會派發 Illuminate\Console\Events\CommandStartingIlluminate\Console\Events\CommandFinished 事件。但是,您可以通過將 Illuminate\Foundation\Testing\WithConsoleEvents trait 添加到類別中,為給定的測試類別啟用這些事件

1<?php
2 
3use Illuminate\Foundation\Testing\WithConsoleEvents;
4 
5uses(WithConsoleEvents::class);
6 
7// ...
1<?php
2 
3namespace Tests\Feature;
4 
5use Illuminate\Foundation\Testing\WithConsoleEvents;
6use Tests\TestCase;
7 
8class ConsoleEventTest extends TestCase
9{
10 use WithConsoleEvents;
11 
12 // ...
13}