del*_*ala 12 php phpunit unit-testing exception
这个问题特定于使用PHPUnit.
PHPUnit自动将php错误转换为异常.有没有办法测试碰巧触发php错误的方法的返回值(内置错误或用户生成的错误通过trigger_error)?
要测试的代码示例:
function load_file ($file)
{
if (! file_exists($file)) {
trigger_error("file {$file} does not exist", E_USER_WARNING);
return false;
}
return file_get_contents($file);
}
Run Code Online (Sandbox Code Playgroud)
这是我想写的测试类型:
public function testLoadFile ()
{
$this->assertFalse(load_file('/some/non-existent/file'));
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是触发的错误导致我的单元测试失败(应该如此).但是如果我试图捕获它,或者设置一个预期的异常,那么在触发错误之后的任何代码都不会执行,所以我无法测试该方法的返回值.
此示例不起作用:
public function testLoadFile ()
{
$this->setExpectedException('Exception');
$result = load_file('/some/non-existent/file');
// code after this point never gets executed
$this->assertFalse($result);
}
Run Code Online (Sandbox Code Playgroud)
有什么想法我能做到这一点吗?
jas*_*son 22
在一个单元测试中无法做到这一点.如果你打破测试返回值,并将通知分成两个不同的测试,这是可能的.
PHPUnit的错误处理程序捕获PHP错误和通知并将它们转换为异常 - 根据定义,它会停止程序执行.您正在测试的功能永远不会返回.但是,您可以暂时禁用将错误转换为异常,即使在运行时也是如此.
通过一个例子,这可能更容易,因此,这两个测试应该是这样的:
public function testLoadFileTriggersErrorWhenFileNotFound()
{
$this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
$result = load_file('/some/non-existent/file');
}
public function testLoadFileRetunsFalseWhenFileNotFound()
{
PHPUnit_Framework_Error_Warning::$enabled = FALSE;
$result = load_file('/some/non-existent/file');
$this->assertFalse($result);
}
Run Code Online (Sandbox Code Playgroud)
这也有使您的测试更清晰,更清晰和自我记录的额外好处.
回复:评论: 这是一个很好的问题,直到我进行了几次测试后才知道.它看起来好像不会恢复默认/原始值,至少从PHPUnit 3.3.17(现在的当前稳定版本)开始.
所以,我实际上会修改上面的内容,如下所示:
public function testLoadFileRetunsFalseWhenFileNotFound()
{
$warningEnabledOrig = PHPUnit_Framework_Error_Warning::$enabled;
PHPUnit_Framework_Error_Warning::$enabled = false;
$result = load_file('/some/non-existent/file');
$this->assertFalse($result);
PHPUnit_Framework_Error_Warning::$enabled = $warningEnabledOrig;
}
Run Code Online (Sandbox Code Playgroud)
回复:第二评论:
这不完全正确.我正在看PHPUnit的错误处理程序,它的工作原理如下:
E_WARNING,则PHPUnit_Framework_Error_Warning用作异常类.E_NOTICE或E_STRICT错误,请使用PHPUnit_Framework_Error_NoticePHPUnit_Framework_Error用作异常类.所以,是的,它的错误E_USER_*没有变成PHPUnit的*_Warning或*_Notice类,它们仍然被转换为通用PHPUnit_Framework_Error异常.
进一步思考
虽然它完全取决于函数的使用方式,但我可能会切换到抛出实际异常而不是触发错误,如果是我的话.是的,这将改变方法的逻辑流程,以及使用该方法的代码......现在,当它无法读取文件时,执行不会停止.但是由您决定所请求的文件是否存在是否真的是异常行为.我倾向于使用异常方式而不是错误/警告/通知,因为它们更容易处理,测试并适用于您的应用程序流程.我通常会保留有关折旧方法调用等的通知.
使用phpunit.xml配置文件并禁用通知/警告/错误到异常转换.手册中的更多细节.它基本上是这样的:
<phpunit convertErrorsToExceptions="false"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false">
</phpunit>
Run Code Online (Sandbox Code Playgroud)