如果一个函数应该杀死PHP,你如何使用PHPUnit来测试这个函数?

2022-08-30 11:52:24

从本质上讲,我有一个名为killProgram的类的方法,它旨在发送hTTP重定向,然后杀死PHP。

我应该如何测试这个?当我运行phpunit时,它不会为该测试返回任何内容,并且完全关闭。

现在我正在考虑让 killProgram 函数引发一个不应该处理的异常,这将允许我断言抛出了异常。

有没有更好的方法?


答案 1

这显然是一个老问题,但我的建议是将代码移动到一个单独的方法中,然后你可以模拟。die()

例如,而不是有这个:

class SomeClass
{
    public function do()
    {
        exit(1);
        // or
        die('Message');
    }
}

这样做:

class SomeClass
{
    public function do()
    {
        $this->terminate(123);
        // or
        $this->terminate('Message');
    }

    protected function terminate($code = 0)
    {
        exit($code);
    }

    // or 
    protected function terminate($message = '')
    {
        die($message);
    }
}

这样,您可以轻松模拟该方法,并且不必担心脚本终止而无法捕获它。terminate

您的测试将如下所示:

class SomeClassTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @expectedExceptionCode 123
     */
    public function testDoFail()
    {
        $mock = $this->getMock('SomeClass');
        $mock->expects($this->any())
             ->method('terminate')
             ->will($this->returnCallback(function($code) {
                 throw new \Exception($code);
             }));

        // run to fail
        $mock->do();
    }
}

我还没有测试代码,但应该非常接近工作状态。


答案 2

由于每个测试都是由相同的PHPUnit进程运行的,如果你在PHP代码中使用exit/die,你将杀死所有东西 - 正如你所注意到的^^

所以,你必须找到另一个解决方案,是的 - 就像返回而不是死亡一样;或引发异常(您可以测试某些测试代码是否引发了预期的异常)。

也许 PHPUnit 3.4 和它的开关(请参阅可选地使用单独的 PHP 进程执行每个测试可能会有所帮助(通过不让所有内容都死掉),但是如果 PHPUnit 没有取回控件,您仍然无法获得测试结果。--process-isolation

我遇到过几次这个问题;通过返回而不是死亡来解决它 - 如果需要,甚至可以返回几次,以便在调用堆栈中返回“足够高”^^
最后,我想我在我的应用程序中不再有任何“死亡”......顺便说一句,在考虑MVC时,这可能更好。


推荐