Подтвердить что ты не робот

Тестирование командных блоков 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
4b9b3361

Ответ 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 и т.д.... до вас.