PHP单元测试:是否可以测试致命错误?

13

顺便提一下,我正在使用 SimpleTest 1.1alpha。

我有一个单例类,并且我想编写一个单元测试来保证这个类是一个单例类,方法是尝试实例化该类(它有一个私有构造函数)。

显然,这会导致致命错误:

Fatal error: Call to private FrontController::__construct()

是否有任何方法可以"捕获"这个致命错误并报告通过的测试?


简单测试中没有单元 ;) - Gordon
@Gordon 我看到这个双关语了,但是我不理解它的意思。 - Stephen
1
也许这个答案可以解释清楚。 - Gordon
老派的单元测试框架不适用于此。为该测试编写一个PHPT,并使用输出的正则表达式将其混合到PHPUnit/SimpleTest案例中。 - mario
3个回答

13

致命错误会停止脚本的执行。

而且没有必要以那种方式测试单例。如果您坚持检查构造函数是否为私有的,可以使用ReflectionClass:getConstructor()

public function testCannotInstantiateExternally()
{
    $reflection = new \ReflectionClass('\My\Namespace\MyClassName');
    $constructor = $reflection->getConstructor();
    $this->assertFalse($constructor->isPublic());
}

另一个需要考虑的问题是,单例类/对象在测试驱动开发中是一个障碍,因为它们很难模拟。


5
这里是Mchl答案的完整代码片段,这样人们就不必浏览文档了...
public function testCannotInstantiateExternally()
{
    $reflection = new \ReflectionClass('\My\Namespace\MyClassName');
    $constructor = $reflection->getConstructor();
    $this->assertFalse($constructor->isPublic());
}

3

您可以使用类似PHPUnit的进程隔离的概念。

这意味着测试代码将在php的子进程中执行。以下示例显示了如何实现此操作。

<?php

// get the test code as string
$testcode = '<?php new '; // will cause a syntax error

// put it in a temporary file
$testfile = tmpfile();
file_put_contents($testfile, $testcode);

exec("php $tempfile", $output, $return_value);

// now you can process the scripts return value and output
// in case of an syntax error the return value is 255
switch($return_value) {
    case 0 :
        echo 'PASSED';
        break;
    default :
        echo 'FAILED ' . $output;

}

// clean up
unlink($testfile);

实际上,这仅适用于检测语法错误,因为(1)脚本通常不会孤立存在,(2)像这样引导整个应用程序是不可行的,(3)它不会创建测试/可重复的上下文,(4)没有设置所有上下文可能会导致假致命错误,如未定义函数。因此,与其执行php $tempfile,不如执行php --no-php-ini --syntax-check $tempfile。http://php.net/manual/en/features.commandline.options.php - aercolino
你能证明吗?我不这么认为。 - hek2mgl
它在控制台中“工作”,因为我看到了致命错误。对于六个无法捕获的错误,$return始终为255,否则始终为0。我认为我需要一个关闭处理程序来获取错误代码。--至于PHPUnit,即使我@runInSeparateProcess一个导致致命错误的单个测试,它仍然显示为“E”。--你的想法很有趣,我之前已经点赞了你。但是要使其正常工作,我认为我需要深入研究PHPUnit并编写补丁或插件。我想知道为什么以前没有人这样做。期望脚本失败是否不合理? - aercolino
现在我明白你的关注点了。我会稍微尝试一下 PHPUnit,可能写一些代码并给你反馈。 - hek2mgl
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/69412/discussion-between-hek2mgl-and-ando。 - hek2mgl
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接