我有一个输出到的类 STDERR
,但我找不到让PHPUnit测试其输出的方法。
班上, PHPUnit_Extensions_OutputTestCase
,也没用。
我有一个输出到的类 STDERR
,但我找不到让PHPUnit测试其输出的方法。
班上, PHPUnit_Extensions_OutputTestCase
,也没用。
我没有看到缓冲的方法 stderr
尽你所能 stdout
,所以我会重构你的类来将执行输出的调用移动到新方法。这将允许您在测试期间模拟该方法,以使用缓冲区验证输出或子类。
例如,假设您有一个列出目录中文件的类。
class DirLister {
public function list($path) {
foreach (scandir($path) as $file) {
echo $file . "\n";
}
}
}
首先,提取呼叫 echo
。使其受到保护,以便您可以覆盖和/或模拟它。
class DirLister {
public function list($path) {
foreach (scandir($path) as $file) {
$this->output($file . "\n");
}
}
protected function output($text) {
echo $text ;
}
}
其次,在测试中模拟或子类化。如果您进行简单的测试或者不期望多次调用,那么模拟很容易 output
。如果要验证大量输出,则子类化缓冲输出会更容易。
class DirListTest extends PHPUnit_Framework_TestCase {
public function testHomeDir() {
$list = $this->getMock('DirList', array('output'));
$list->expects($this->at(0))->method('output')->with("a\n");
$list->expects($this->at(1))->method('output')->with("b\n");
$list->expects($this->at(2))->method('output')->with("c\n");
$list->list('_files/DirList'); // contains files 'a', 'b', and 'c'
}
}
重写 output
缓冲所有 $text
进入内部缓冲区留给读者练习。
你不能拦截和 fwrite(STDERR);
在phpunit的帮助下从测试用例中。就此而言,你甚至无法拦截 fwrite(STDOUT);
,甚至没有输出缓冲。
因为我假设你真的不想注射 STDERR
进入你的“errorOutputWriter
“(因为这个类在其他地方写的没有任何意义)这是我建议那种小黑客的极少数情况之一:
<?php
class errorStreamWriterTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$this->writer = new errorStreamWriter();
$streamProp = new ReflectionProperty($this->writer, 'errorStream');
$this->stream = fopen('php://memory', 'rw');
$streamProp->setAccessible(true);
$streamProp->setValue($this->writer, $this->stream);
}
public function testLog() {
$this->writer->log("myMessage");
fseek($this->stream, 0);
$this->assertSame(
"Error: myMessage",
stream_get_contents($this->stream)
);
}
}
/* Original writer*/
class errorStreamWriter {
public function log($message) {
fwrite(STDERR, "Error: $message");
}
}
// New writer:
class errorStreamWriter {
protected $errorStream = STDERR;
public function log($message) {
fwrite($this->errorStream, "Error: $message");
}
}
它取出stderr流并将其替换为内存流,并在测试用例中读回一个以查看是否写入了正确的输出。
通常,我肯定会说“在类中注入文件路径”但是 STDERR
这对我没有任何意义,所以这将是我的解决方案。
phpunit stderrTest.php
PHPUnit @package_version@ by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 5.00Mb
OK (1 test, 1 assertion)
在给它一些想法后,我会说没有像想象的那样 errorSteamWriter
作为一个班级也可能会成功。
只是有一个 StreamWriter
并用它构建它 new StreamWriter(STDERR);
将导致一个可测试的类很好,可以在应用程序中重复用于很多目的而无需硬编码某种“这就是错误发生在它自己的类中”并增加了灵活性。
只是想添加这个作为一个选项,以避免“丑陋”的测试选项:)
使用流过滤器捕获/重定向输出到STDERR。以下示例实际上是upercases并重定向到STDOUT,但传达了基本思想。
class RedirectFilter extends php_user_filter {
static $redirect;
function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = strtoupper($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
fwrite(STDOUT, $bucket->data);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("redirect", "RedirectFilter")
or die("Failed to register filter");
function start_redirect() {
RedirectFilter::$redirect = stream_filter_prepend(STDERR, "redirect", STREAM_FILTER_WRITE);
}
function stop_redirect() {
stream_filter_remove( RedirectFilter::$redirect);
}
start_redirect();
fwrite(STDERR, "test 1\n");
stop_redirect();