Laravel 5.4 - 5.6
Фактическая проблема здесь заключается в том, что при запуске команды консоли ожидается ввод данных пользователем, однако мы выполняем это через PHPUnit, поэтому мы не можем ничего ввести.
Усиление ограничений в модульном тестировании может поначалу разочаровывать, однако ограничения, которые вы обнаружите, могут оказаться скрытым благословением.
В настоящее время ваша реализация тесно связана с представлением (консольная команда, то есть представление с правами администратора, но, тем не менее, с представлением). Что можно сделать здесь, так это поместить любую логику в отдельный класс, который MyCommand
может использовать, и какой PHPUnit может проверить самостоятельно. Мы знаем , что основы выполнения пользовательской команды работают, как продемонстрировано в модульных тестах Laravel, поэтому мы можем переложить нашу логику в отдельный тестируемый класс.
Ваш новый класс может выглядеть примерно так:
class CommandLogic
{
public function getQuestion1Text()
{
return 'Ask question 1';
}
public function getQuestion2Text()
{
return 'Ask question 2';
}
public function getQuestion3Text()
{
return 'Ask question 3';
}
public function submit(array $input)
{
$validator = \Illuminate\Support\Facades\Validator::make($input, [
'answer1' => 'required',
'answer2' => 'required',
'answer3' => 'required',
]);
if ($validator->fails()) {
// processing error
} else {
// saving to DB
}
}
}
... ваш фактический юнит-тест, что-то вроде этого:
$commandLogic = new CommandLogic();
$sampleInput = [
'answer1' => 'test1',
'answer2' => 'test2',
'answer3' => 'test3',
];
$commandLogic->submit($sampleInput);
$this->assertDatabaseHas('myTable', [
'question1' => 'test1'
]);
... и ваша консольная команда, что-то вроде этого:
public function handle()
{
$commandLogic = new CommandLogic();
$input['answer1'] = $this->ask($commandLogic->getQuestion1Text());
$input['answer2'] = $this->ask($commandLogic->getQuestion2Text());
$input['answer3'] = $this->ask($commandLogic->getQuestion3Text());
$commandLogic->submit($input);
}
Это обеспечивает соблюдение принципа единой ответственности и разделяет движущиеся части в вашей кодовой базе. Я знаю, что это может показаться копом, но протестировать этот материал в Laravel 5.4 сложно. Если вы хотите перейти на версию 5.7 или выше, читайте ниже ...
Laravel 5.7 +
В Laravel 5.7 появилась возможность запускать консольные тесты, которые удовлетворяют точным требованиям, которые задает этот вопрос - https://laravel.com/docs/5.7/console-tests. Это скорее полный интеграционный тест, а не модульный тест.