跳至内容

控制台测试

介绍

除了简化 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提供的search或功能,则可以使用断言来模拟用户的输入、搜索结果和选择:multisearchexpectsSearch

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}

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(): 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 ], [
6 [1, 'taylor@example.com'],
7 [2, 'abigail@example.com'],
8 ]);

控制台事件

默认情况下,运行应用测试时不会调度Illuminate\Console\Events\CommandStarting和事件。但是,您可以通过向给定的测试类添加以下特征来启用这些事件:Illuminate\Console\Events\CommandFinishedIlluminate\Foundation\Testing\WithConsoleEvents

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}