基本上我有一个名为killProgram的类的方法,它用于发送hTTP重定向然后杀死PHP。
我该如何测试?当我运行phpunit时,它不返回该测试的任何内容,并完全关闭。
现在我正在考虑让killProgram函数抛出一个不应该被处理的异常,这将允许我断言抛出异常。
有更好的方法吗?
答案 0 :(得分:23)
由于每个测试都是由同一个PHPUnit进程运行的,如果你在PHP代码中使用exit / die,你会杀死所有东西 - 正如你注意到的那样^^
所以,你必须找到另一种解决方案,是的 - 就像回归而不是死亡一样;或抛出异常(您可以测试一些经过测试的代码是否抛出了预期的异常)。
也许PHPUnit 3.4及其--process-isolation
切换(请参阅Optionally execute each test using a separate PHP process)可能帮助(没有让所有事情都死亡),但你仍然不愿意如果PHPUnit没有得到控制权,那么就无法获得测试结果。
我有几次这个问题;通过返回而不是死亡来解决它 - 如果需要,甚至返回几次,以便在调用堆栈中返回“足够高”^^
最后,我想我的应用程序中没有任何“死”......当考虑MVC时,可能会更好。顺便说一句。
答案 1 :(得分:20)
这显然是一个老问题,但我的建议是将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 :(得分:14)
无需更改代码只是为了能够对其进行测试,您只需使用set_exit_overload()
(由来自同一作者的test_helpers
提供的PHPUnit)。
答案 3 :(得分:7)
我意识到你已经接受了这个答案,这是一个老问题,但我认为这可能对某人有用,所以这里有:
您可以使用die()
(或您自己的异常类),而不是使用throw new RuntimeException()
,这也将暂停程序执行(尽管以不同的方式)并使用PHPUnit的{{3}抓住它。如果您希望在遇到异常时将脚本发送到die()
,请在用户级别打印绝对没有内容,请查看setExpectedException()
。
具体来说,我正在考虑将set_exception_handler()
- 调用放入测试不使用的引导程序文件的情况,因此无论方案如何,处理程序都不会在那里触发,所以没有任何东西干扰PHPUnit的本机异常处理。
答案 4 :(得分:4)
这与我已经获得一些遗留代码以通过测试的一系列问题有关。所以我想出了一个像这样的Testable类......
class Testable {
static function exitphp() {
if (defined('UNIT_TESTING')) {
throw new TestingPhpExitException();
} else {
exit();
}
}
}
现在我只需用Testable :: exitphp()替换对exit()的调用。
如果它正在测试中我只是定义UNIT_TESTING,在生产中我没有。看起来像一个简单的模拟。
答案 5 :(得分:0)
您可以杀死脚本或引发异常,具体取决于环境变量的值...
因此,您在生产中会杀死应用程序或在测试环境中抛出异常。
任何呼叫死亡或退出的请求,都会杀死整个过程...
这本来应该是评论,但我无法评论我的声誉点的水平。