Как написать модульные тесты для интерактивного консольного приложения

У меня есть консольное приложение (написанное как команда Symfony2), которое считывает ввод от пользователя через STDIN и с помощью readline , пользовательский ввод затем передается в eval()

Все дело только в том, что у вас есть «отладочная оболочка» (что-то вроде php -a ), но в рамках проекта env и доступа к контейнерам зависимостей.

Я хотел бы написать unit-tests для этой команды, но я нажимаю на стену, как (и это возможно) писать тесты PHPUnit для этого поведения?

    Я не знаком с вещью Sf2 Command, но в документах Sf2 есть пример тестирования на http://symfony.com/doc/2.0/components/console.html#testing-commands

    В общем, вы можете отделить STDIN и STDOUT от своего консольного приложения, чтобы вы могли заменить его другим ресурсом потока, например fopen(php://memory) . Вместо readline вы используете

     fwrite($outputStream, 'Prompt'); $line = stream_get_line($inputStream, 1024, PHP_EOL); 

    Идея состоит в том, чтобы сделать ваш компонент тестируемым, не требуя реальной среды консоли. Используя этот подход, вы можете в любое время проверить содержимое Stream в своем тесте. Поэтому, если вы запускаете команду «foo» в своем консольном приложении и хотите проверить, что выход «bar», вы просто перематываете соответствующий ресурс и читаете его содержимое . Альтернативой может быть использование SplTempFileObject .

     class ConsoleApp … public function __construct($inputStream, $outputStream) { $this->inputStream = $inputStream; $this->outputStream = $outputStream; } } 

    В вашем сценарии реального мира вы создадите консольное приложение с

     $app = new ConsoleApp(STDIN, STDOUT); 

    Но в вашем тесте вы можете настроить ConsoleApp с потоком по вашему выбору:

     public function setup() { $i = fopen('php://memory', 'w'); $o = fopen('php://memory', 'w'); $this->consoleApp = new ConsoleApp($i, $o); } 

    Примером UnitTest, использующим этот метод для выхода, будет