test the return value of a method that triggers an error with PHPUnit(使用 PHPUnit 测试触发错误的方法的返回值)
问题描述
This question is specific to using PHPUnit.
PHPUnit automatically converts php errors to exceptions. Is there a way to test the return value of a method that happens to trigger a php error (either built-in errors or user generated errors via trigger_error)?
Example of code to test:
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);
}
This is the type of test I want to write:
public function testLoadFile ()
{
$this->assertFalse(load_file('/some/non-existent/file'));
}
The problem I am having is that the triggered error causes my unit test to fail (as it should). But if I try to catch it, or set an expected exception any code that after the error is triggered never executes so I have no way of testing the return value of the method.
This example doesn't work:
public function testLoadFile ()
{
$this->setExpectedException('Exception');
$result = load_file('/some/non-existent/file');
// code after this point never gets executed
$this->assertFalse($result);
}
Any ideas how I could achieve this?
There is no way to do this within one unit test. It is possible if you break up testing the return value, and the notice into two different tests.
PHPUnit's error handler catches PHP errors and notices and converts them into Exceptions--which by definition stops program execution. The function you are testing never returns at all. You can, however, temporarily disable the conversion of errors into exceptions, even at runtime.
This is probably easier with an example, so, here's what the two tests should look like:
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);
}
This also has the added bonus of making your tests clearer, cleaner and self documenting.
Re: Comment: That's a great question, and I had no idea until I ran a couple of tests. It looks as if it will not restore the default/original value, at least as of PHPUnit 3.3.17 (the current stable release right now).
So, I would actually amend the above to look like so:
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;
}
Re: Second Comment:
That's not completely true. I'm looking at PHPUnit's error handler, and it works as follows:
- If it is an
E_WARNING
, usePHPUnit_Framework_Error_Warning
as an exception class. - If it is an
E_NOTICE
orE_STRICT
error, usePHPUnit_Framework_Error_Notice
- Else, use
PHPUnit_Framework_Error
as the exception class.
So, yes, errors of the E_USER_*
are not turned into PHPUnit's *_Warning or *_Notice class, they are still transformed into a generic PHPUnit_Framework_Error
exception.
Further Thoughts
While it depends exactly on how the function is used, I'd probably switch to throwing an actual exception instead of triggering an error, if it were me. Yes, this would change the logic flow of the method, and the code that uses the method... right now the execution does not stop when it cannot read a file. But that's up to you to decide whether the requested file not existing is truly exceptional behaviour. I tend to use exceptions way more than errors/warnings/notices, because they are easier to handle, test and work into your application flow. I usually reserve the notices for things like depreciated method calls, etc.
这篇关于使用 PHPUnit 测试触发错误的方法的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 PHPUnit 测试触发错误的方法的返回值
基础教程推荐
- 通过 PHP SoapClient 请求发送原始 XML 2021-01-01
- mysqli_insert_id 是否有可能在高流量应用程序中返回 2021-01-01
- Libpuzzle 索引数百万张图片? 2022-01-01
- WooCommerce 中选定产品类别的自定义产品价格后缀 2021-01-01
- 超薄框架REST服务两次获得输出 2022-01-01
- XAMPP 服务器不加载 CSS 文件 2022-01-01
- 在 Woocommerce 中根据运输方式和付款方式添加费用 2021-01-01
- 如何在 PHP 中的请求之间持久化对象 2022-01-01
- 在多维数组中查找最大值 2021-01-01
- 在 PHP 中强制下载文件 - 在 Joomla 框架内 2022-01-01