我正在将我的Laravel 4.2应用程序迁移到5.1(从5.0开始),并且我的控制台命令单元测试很麻烦。我有工匠命令,我需要测试生成的控制台输出,正确的问题/响应处理以及与其他服务的交互(使用模拟)。尽管如此,Laravel文档在测试控制台命令时仍然是无声的。
我终于找到了创建这些测试的方法,但感觉就像是对setLaravel
和setApplication
次调用的黑客攻击。
有更好的方法吗?我希望我可以将我的模拟实例添加到Laravel IoC容器中,并让它创建命令以测试所有正确设置的内容。我担心我的单元测试会在较新的Laravel版本中轻易破解。
这是我的单元测试:
使用陈述:
use Mockery as m;
use App\Console\Commands\AddClientCommand;
use Symfony\Component\Console\Tester\CommandTester;
设置
public function setUp() {
parent::setUp();
$this->store = m::mock('App\Services\Store');
$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('Illuminate\Contracts\Foundation\Application'));
// 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('Symfony\Component\Console\Application'));
}
作为命令参数提供的输入。检查控制台输出
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 Client\n"));
$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;
}
答案 0 :(得分:9)
我之前做过如下操作 - 我的控制台命令返回一个json响应:
public function getConsoleResponse()
{
$kernel = $this->app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'test:command', // put your command name here
]),
$output = new Symfony\Component\Console\Output\BufferedOutput
);
return json_decode($output->fetch(), true);
}
所以,如果你想把它放在它自己的命令测试器类中,或者作为TestCase中的一个函数等等......由你决定。
答案 1 :(得分:2)
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\Console\Output\BufferedOutput;
$output = new BufferedOutput();
Artisan::call('passport:client', [
'--password' => true,
'--name' => 'Temp Client',
'--no-interaction' => true,
], $output);
$stringOutput = $output->fetch();