Тестирование командных блоков Laravel 5 console (artisan)
Я переношу свое приложение Laravel 4.2 на 5.1 (начиная с 5.0) и испытываю большие проблемы с моими тестовыми модулями в консоли. У меня есть команды мастеров, для которых мне нужно протестировать выпущенный выпуск консоли, правильную обработку вопросов/ответов и взаимодействие с другими службами (с использованием mocks). По всем его достоинствам, к сожалению, к документу Laravel не относится к тестированию команд консоли.
Наконец-то я нашел способ создания этих тестов, но это похоже на взлом с этими вызовами setLaravel
и setApplication
.
Есть ли лучший способ сделать это? Хотелось бы, чтобы я мог добавить свои макеты в контейнер Laravel IoC и позволить ему создавать команды для тестирования со всем, что правильно установлено. Боюсь, что мои юнит-тесты легко ломаются с новыми версиями Laravel.
Здесь мой unit test:
Использовать утверждения:
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;
}
Обновления
- Это не работает в Laravel 5.1 # 11946
Ответы
Ответ 1
Я сделал это раньше: моя консольная команда возвращает ответ 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 и т.д.... до вас.