Php 如何为交互式控制台应用程序编写单元测试

Php 如何为交互式控制台应用程序编写单元测试,php,console,phpunit,stdio,Php,Console,Phpunit,Stdio,我有一个控制台应用程序(作为Symfony2命令编写),它通过STDIN读取用户输入,在readline的帮助下,用户输入被传递到eval() 整个过程只是为了拥有“debug shell”(类似于php-a),但是在projectenv和依赖注入容器访问中 我想为这个命令编写单元测试,但我正在讨论如何(以及是否可能)为这个行为编写PHPUnit测试?我不熟悉Sf2命令,但是Sf2文档中有一个关于测试它的示例 通常,您可以将STDIN和STDOUT与控制台应用程序分离,这样您就可以用另一个流资源

我有一个控制台应用程序(作为Symfony2命令编写),它通过
STDIN
读取用户输入,在
readline
的帮助下,用户输入被传递到
eval()

整个过程只是为了拥有“debug shell”(类似于
php-a
),但是在projectenv和依赖注入容器访问中


我想为这个命令编写单元测试,但我正在讨论如何(以及是否可能)为这个行为编写PHPUnit测试?

我不熟悉Sf2命令,但是Sf2文档中有一个关于测试它的示例

通常,您可以将
STDIN
STDOUT
与控制台应用程序分离,这样您就可以用另一个流资源(如
fopen)替换它(php://memory)
。您使用

fwrite($outputStream, 'Prompt');
$line = stream_get_line($inputStream, 1024, PHP_EOL);
其思想是使您的组件可测试,而不需要真正的控制台环境。使用这种方法,您可以在测试中随时检查流的内容。另一种方法是使用
SplTempFileObject

class ConsoleApp
…
    public function __construct($inputStream, $outputStream)
    {
        $this->inputStream = $inputStream;
        $this->outputStream = $outputStream;
    }
}
在您的真实场景中,您将使用

$app = new ConsoleApp(STDIN, STDOUT);
但在测试中,您可以使用自己选择的流设置
控制台App

public function setup()
{
    $i = fopen('php://memory', 'w');
    $o = fopen('php://memory', 'w');
    $this->consoleApp = new ConsoleApp($i, $o);
}
将此方法用于外流的单元测试示例如下