控制台测试
介绍
除了简化 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(): void5{6 $this->artisan('inspire')->assertExitCode(0);7}
您可以使用该assertNotExitCode
方法来断言命令没有以给定的退出代码退出:
1$this->artisan('inspire')->assertNotExitCode(1);
当然,所有终端命令通常都会在成功时以状态码退出0
,在失败时以非零退出码退出。因此,为了方便起见,你可以使用assertSuccessful
和assertFailed
断言来断言给定命令是否以成功退出码退出:
1$this->artisan('inspire')->assertSuccessful();2 3$this->artisan('inspire')->assertFailed();
输入/输出期望
Laravel 允许您使用 方法轻松地“模拟”控制台命令的用户输入。此外,您还可以使用和方法expectsQuestion
指定退出代码以及您希望控制台命令输出的文本。例如,考虑以下控制台命令:assertExitCode
expectsOutput
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提供的search
或功能,则可以使用断言来模拟用户的输入、搜索结果和选择:multisearch
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(): void5{6 $this->artisan('example')7 ->doesntExpectOutput()8 ->assertExitCode(0);9}
和expectsOutputToContain
方法doesntExpectOutputToContain
可用于对部分输出做出断言:
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(): void5{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 ], [6 [1, 'taylor@example.com'],7 [2, 'abigail@example.com'],8 ]);
控制台事件
默认情况下,运行应用测试时不会调度Illuminate\Console\Events\CommandStarting
和事件。但是,您可以通过向给定的测试类添加以下特征来启用这些事件:Illuminate\Console\Events\CommandFinished
Illuminate\Foundation\Testing\WithConsoleEvents
1<?php2 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}