Zee*_*cer 35 php phpunit unit-testing
基本上我有一个名为killProgram的类的方法,它用于发送hTTP重定向然后杀死PHP.
我该怎么测试呢?当我运行phpunit时,它不返回该测试的任何内容,并完全关闭.
现在我正在考虑让killProgram函数抛出一个不应该被处理的异常,这将允许我断言抛出异常.
有没有更好的办法?
Pas*_*TIN 23
由于每个测试都是由相同的PHPUnit进程运行的,如果你在PHP代码中使用exit/die,你会杀死所有东西 - 正如你注意到的那样^^
所以,你必须找到另一种解决方案,是的 - 就像回归而不是死亡一样; 或抛出异常(您可以测试某些经过测试的代码是否抛出了预期的异常).
也许PHPUnit 3.4和它的--process-isolation
开关(参见使用单独的PHP进程可选地执行每个测试)可能有所帮助(通过不会让所有东西都死掉),但如果PHPUnit没有得到,你仍然无法获得测试结果控制回来.
我有几次这个问题; 通过返回,而不是垂死解决了这个问题-即使回国几次,如果需要的话,回去"足够高",在调用堆栈^^
最后,我想我没有在我的应用程序的任何"死"了. ..当考虑MVC时,它可能更好,顺便说一句.
And*_*ris 22
这显然是一个老问题,但我的建议是将代码移动die()
到一个单独的方法,然后你可以模拟.
举个例子,而不是这个:
class SomeClass
{
public function do()
{
exit(1);
// or
die('Message');
}
}
Run Code Online (Sandbox Code Playgroud)
做这个:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以轻松地模拟该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();
}
}
Run Code Online (Sandbox Code Playgroud)
我没有测试过代码,但应该非常接近工作状态.
小智 14
没有必要更改代码只是为了能够测试它,你可以简单地使用set_exit_overload()
(由test_helpers
同一作者提供的PHPUnit).
我意识到你已经接受了这个答案,这是一个老问题,但我认为这可能对某人有用,所以这里有:
die()
您可以使用throw new RuntimeException()
(或者您自己的异常类)而不是使用它,这也将暂停程序执行(尽管以不同的方式)并使用PHPUnit setExpectedException()
来捕获它.如果您希望脚本die()
在遇到该异常时,在用户级别打印绝对没有任何内容,请查看set_exception_handler()
.
具体来说,我正在考虑将set_exception_handler()
-call放入测试不使用的引导程序文件的情况,因此无论情况如何,处理程序都不会触发,因此不会干扰PHPUnit的本机异常处理.
这与我在获取一些遗留代码以通过测试时遇到的一系列问题有关。所以我想出了一个像这样的可测试类......
class Testable {
static function exitphp() {
if (defined('UNIT_TESTING')) {
throw new TestingPhpExitException();
} else {
exit();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我只需用 Testable::exitphp() 替换对 exit() 的调用。
如果它在测试中,我只定义 UNIT_TESTING,在生产中我没有。看起来像一个简单的 Mock。