我正在使用Symfony\Component\Console\Output\ConsoleOutput
写入控制台。
明确地说,我写信给php://stdout
。
在我的单元测试中,我希望能够检查输出到控制台。
使用PHPUnit方法expectOutputString()
,我可以检查输出:
// Passes, as expected
public function testOutputBufferingEcho()
{
$this->expectOutputString('Hello');
echo 'Hello';
}
这也适用于输出到php://output
:
// Passes, as expected
public function testOutputBufferingOutput()
{
$this->expectOutputString('Hello');
$out = fopen('php://output', 'w');
fputs ($out, 'Hello');
fclose($out);
}
但是,它不适用于输出到php://stdout
(ConsoleOutput
默认使用的输出):
// Failed asserting that two strings are equal.
// --- Expected
// +++ Actual
// @@ @@
// -'Hello'
// +''
public function testOutputBufferingStdOut()
{
$this->expectOutputString('Hello');
$out = fopen('php://stdout', 'w');
fputs ($out, 'Hello');
fclose($out);
}
此外,似乎无法使用ob_*
函数直接将输出捕获到php://stdout
。
有没有用PHPUnit测试输出到php://stdout
?
或者是否有其他方法可以将输出捕获到php://stdout
到字符串中(在PHPUnit中进行测试)?
以上测试在PHPUnit 5.5.5中运行。
提前谢谢。
答案 0 :(得分:9)
捕获php://stdout
(或任何其他流)的快速而肮脏的方法是使用更快更脏的流过滤器。
class Intercept extends php_user_filter
{
public static $cache = '';
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
self::$cache .= $bucket->data;
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("intercept", "Intercept");
$stdout = fopen('php://stdout', 'w'); // or $yerSymfonyThingy->getStream()
stream_filter_append($stdout, "intercept");
fwrite($stdout, "Hello\n");
var_dump(Intercept::$cache);
Hello
string(6) "Hello
"
写入流中的所有内容都会在Intercept::$cache
中收集,供您阅读。
如果您愿意,可以将PSFS_PASS_ON
替换为PSFS_FEED_ME
,以阻止正常输出流。
答案 1 :(得分:1)
有一种方法可以将STDOUT替换为任何其他资源:关闭它。下一个打开的资源将具有文件描述符" 1" (STDOUT)因为这是第一个免费的。
fclose(STDOUT);
$fakestdout = fopen('php://memory', 'r+');
现在任何输出都转到$fakestdout
,你可以在测试用例中读取它。
唯一的问题是此操作无法恢复。因此,从现在起,每次尝试写入STDOUT(包括" echo")都会在关闭之后转到$fakestdout
或其他地方。 关闭后无法重新打开STDOUT。
但是如果你运行带有--stderr
参数的PHPUnit来为PHPUnit输出使用STDERR,那么这应该可行。