我正在将我的 Laravel 4.2 应用程序迁移到 5.1(从 5.0 开始),并且我的控制台命令单元测试遇到了很多麻烦。我有工匠命令,我需要测试生成的控制台输出、正确的问题/响应处理以及与其他服务的交互(使用模拟)。尽管有其所有优点,但不幸的是,Laravel文档在测试控制台命令方面保持沉默。
我终于找到了创建这些测试的方法,但这感觉就像是那些setLaravel
和setApplication
调用的黑客。
有没有更好的方法可以做到这一点?我希望我可以将我的模拟实例添加到 Laravel IoC 容器中,并让它创建命令以正确设置所有内容进行测试。恐怕我的单元测试很容易被更新的Laravel版本破坏。
这是我的单元测试:
使用语句:
use Mockery as m;
use AppConsoleCommandsAddClientCommand;
use SymfonyComponentConsoleTesterCommandTester;
设置
public function setUp() {
parent::setUp();
$this->store = m::mock('AppServicesStore');
$this->command = new AddClientCommand($this->store);
// Taken from laravel/framework artisan command unit tests
// (e.g. tests/Database/DatabaseMigrationRollbackCommandTest.php)
$this->command->setLaravel($this->app->make('IlluminateContractsFoundationApplication'));
// Required to provide input to command questions (provides command->getHelper())
// Taken from ??? when I first built my command tests in Laravel 4.2
$this->command->setApplication($this->app->make('SymfonyComponentConsoleApplication'));
}
作为命令参数提供的输入。检查控制台输出
public function testReadCommandOutput() {
$commandTester = new CommandTester($this->command);
$result = $commandTester->execute([
'--client-name' => 'New Client',
]);
$this->assertSame(0, $result);
$templatePath = $this->testTemplate;
// Check console output
$this->assertEquals(1, preg_match('/^Client 'New Client' was added./m', $commandTester->getDisplay()));
}
模拟键盘键提供的输入
public function testAnswerQuestions() {
$commandTester = new CommandTester($this->command);
// Simulate keyboard input in console for new client
$inputs = $this->command->getHelper('question');
$inputs->setInputStream($this->getInputStream("New Clientn"));
$result = $commandTester->execute([]);
$this->assertSame(0, $result);
$templatePath = $this->testTemplate;
// Check console output
$this->assertEquals(1, preg_match('/^Client 'New Client' was added./m', $commandTester->getDisplay()));
}
protected function getInputStream($input) {
$stream = fopen('php://memory', 'r+', false);
fputs($stream, $input);
rewind($stream);
return $stream;
}
更新
- 这在 Laravel 5.1 #11946 中不起作用
我之前已经这样做了,如下所示 - 我的控制台命令返回一个 json 响应:
public function getConsoleResponse()
{
$kernel = $this->app->make(IlluminateContractsConsoleKernel::class);
$status = $kernel->handle(
$input = new SymfonyComponentConsoleInputArrayInput([
'command' => 'test:command', // put your command name here
]),
$output = new SymfonyComponentConsoleOutputBufferedOutput
);
return json_decode($output->fetch(), true);
}
因此,如果您想将其放在它自己的命令测试器类中,或者作为TestCase等中的函数......取决于您。
use IlluminateSupportFacadesArtisan;
use SymfonyComponentConsoleOutputBufferedOutput;
$output = new BufferedOutput();
Artisan::call('passport:client', [
'--password' => true,
'--name' => 'Temp Client',
'--no-interaction' => true,
], $output);
$stringOutput = $output->fetch();