12

FWIW 我正在使用 SimpleTest 1.1alpha。

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

这显然会导致致命错误:

致命错误:调用私有 FrontController::__construct()

有没有办法“捕捉”那个致命错误并报告通过的测试?

4

3 回答 3

13

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

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

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

要考虑的另一件事是单例类/对象是 TTD 中的一个障碍,因为它们难以模拟。

于 2011-01-20T23:24:15.807 回答
5

这是 Mchl 答案的完整代码片段,因此人们不必阅读文档...

public function testCannotInstantiateExternally()
{
    $reflection = new \ReflectionClass('\My\Namespace\MyClassName');
    $constructor = $reflection->getConstructor();
    $this->assertFalse($constructor->isPublic());
}
于 2014-08-29T06:30:48.080 回答
3

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

这意味着测试代码将在 php.ini 的子进程中执行。这个例子展示了它是如何工作的。

<?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);
于 2012-12-20T22:28:20.757 回答