Как проверить команды Artisan с помощью ask () в Laravel 5.4 - PullRequest
0 голосов
/ 09 мая 2018

Попытка написать тест для команды laravel php artisan с помощью функции ask (). Я никогда раньше не использовал насмешки, но когда я пытаюсь запустить тест, он зависает, так что, я думаю, я делаю что-то не так.

MyCommand.php:

public function handle()
    {
        $input['answer1'] = $this->ask('Ask question 1');
        $input['answer2'] = $this->ask('Ask question 2');
        $input['answer3'] = $this->ask('Ask question 3');


        //--- processing validation        
        $validator = Validator::make($input, [
            'answer1' => 'required',
            'answer2' => 'required',
            'answer3' => 'required',

        ]);

        if ($validator->fails()) {
            // processing error
            }
        } else {
            // saving to DB
        }
    }

И мой юнит-тест:

    $command = m::mock('\App\Console\Commands\Questions');


            $command->shouldReceive('ask')              
                  ->andReturn('Answer 1')
                  ->shouldReceive('ask')
                  ->andReturn('Answer 2')
                  ->shouldReceive('ask')
                  ->andReturn('Answer 3')


            $this->artisan('myCommand:toRun');

$this->assertDatabaseHas('myTable', [
            'question1' => 'answer1'
        ]);

//

1 Ответ

0 голосов
/ 14 февраля 2019

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. Это скорее полный интеграционный тест, а не модульный тест.

...