测试 CLI 命令
使用 MockInputOutput
Added in version 4.5.0.
MockInputOutput
MockInputOutput 提供了一种便捷的方式来测试需要用户输入的命令,例如 CLI::prompt()、CLI::wait() 和 CLI::input()。
测试执行期间,可用 MockInputOutput 替换 InputOutput 类,从而捕获输入和输出。
备注
使用 MockInputOutput 时,无需再使用
StreamFilterTrait、CITestStreamFilter 和
PhpStreamWrapper。
辅助方法
getOutput(?int $index = null): string
获取输出内容。
调用
$io->getOutput()时,返回完整输出字符串。指定
0或正数时,返回输出数组中对应索引的项。 每项是单次CLI::fwrite()调用的输出。指定负数
-n时,返回输出数组倒数第n项。
getOutputs(): array
返回输出数组。每项是单次 CLI::fwrite() 调用的输出。
使用方法
CLI::setInputOutput()可将MockInputOutput实例设置到CLI类。CLI::resetInputOutput()重置CLI类中的InputOutput实例。MockInputOutput::setInputs()设置用户输入数组。MockInputOutput::getOutput()获取命令输出。
以下测试代码用于测试命令 spark db:table:
<?php
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\Mock\MockInputOutput;
final class DbTableTest extends CIUnitTestCase
{
use DatabaseTestTrait;
protected $migrateOnce = true;
public function testDbTable(): void
{
// Set MockInputOutput to CLI.
$io = new MockInputOutput();
CLI::setInputOutput($io);
// User will input "a" (invalid value) and "0".
$io->setInputs(['a', '0']);
command('db:table');
// Get the whole output string.
$output = $io->getOutput();
$expected = 'Which table do you want to see? [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]: a';
$this->assertStringContainsString($expected, $output);
$expected = 'Data of Table "db_migrations":';
$this->assertStringContainsString($expected, $output);
// Remove MockInputOutput.
CLI::resetInputOutput();
}
}
不使用 MockInputOutput
测试 CLI 输出
StreamFilterTrait
Added in version 4.3.0.
StreamFilterTrait 提供了一组替代方法。
有些情况测试起来比较困难。此时捕获流(如 PHP 自身的 STDOUT 或 STDERR)可能会有帮助。StreamFilterTrait 可用于捕获指定流的输出。
使用方法
StreamFilterTrait::getStreamFilterBuffer()获取缓冲区捕获的数据。StreamFilterTrait::resetStreamFilterBuffer()重置捕获的数据。
测试用例中的使用示例:
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\StreamFilterTrait;
final class SomeTest extends CIUnitTestCase
{
use StreamFilterTrait;
public function testSomeOutput(): void
{
CLI::write('first.');
$this->assertSame("\nfirst.\n", $this->getStreamFilterBuffer());
$this->resetStreamFilterBuffer();
CLI::write('second.');
$this->assertSame("second.\n", $this->getStreamFilterBuffer());
}
}
StreamFilterTrait 包含一个会自动调用的配置方法。
详见 测试 Trait。
如果测试中重写了 setUp() 或 tearDown() 方法,则必须分别调用 parent::setUp() 和
parent::tearDown() 方法以完成 StreamFilterTrait 的配置。
CITestStreamFilter
CITestStreamFilter 用于手动/单次场景。
如果只需在单个测试中捕获流,可以不使用 StreamFilterTrait trait,改为手动 为流添加过滤器。
使用方法
CITestStreamFilter::registration()注册过滤器。CITestStreamFilter::addOutputFilter()为输出流添加过滤器。CITestStreamFilter::addErrorFilter()为错误流添加过滤器。CITestStreamFilter::removeOutputFilter()从输出流移除过滤器。CITestStreamFilter::removeErrorFilter()从错误流移除过滤器。
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Filters\CITestStreamFilter;
final class SomeTest extends CIUnitTestCase
{
public function testSomeOutput(): void
{
CITestStreamFilter::registration();
CITestStreamFilter::addOutputFilter();
CLI::write('first.');
CITestStreamFilter::removeOutputFilter();
}
}
测试 CLI 输入
PhpStreamWrapper
Added in version 4.3.0.
PhpStreamWrapper 提供了一种方式来测试需要用户输入的方法,
例如 CLI::prompt()、CLI::wait() 和 CLI::input()。
备注
PhpStreamWrapper 是一个流封装类。 如果不了解 PHP 的流封装,请参阅 PHP 手册中的 streamWrapper 类。
使用方法
PhpStreamWrapper::register()将PhpStreamWrapper注册到php协议。PhpStreamWrapper::restore()将 php 协议恢复为 PHP 内置的流封装。PhpStreamWrapper::setContent()设置输入数据。
重要
PhpStreamWrapper 仅用于测试 php://stdin。
但注册后,它将处理所有 php 协议 流,
例如 php://stdout、php://stderr、php://memory。
因此强烈建议仅在需要时注册/取消注册 PhpStreamWrapper。
否则,注册期间会干扰其他 PHP 内置流。
测试用例中的使用示例:
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\PhpStreamWrapper;
final class SomeTest extends CIUnitTestCase
{
public function testPrompt(): void
{
// Register the PhpStreamWrapper.
PhpStreamWrapper::register();
// Set the user input to 'red'. It will be provided as `php://stdin` output.
$expected = 'red';
PhpStreamWrapper::setContent($expected);
$output = CLI::prompt('What is your favorite color?');
$this->assertSame($expected, $output);
// Restore php protocol wrapper.
PhpStreamWrapper::restore();
}
}