这个问题是,具体到使用进行.

进行自动转换php错误为例外情况。 有没有一种方法来测试回报价值的方法发生的触发一个php error(无论是内在的错误或用户产生错误通过 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);
}

这种类型的测试我想写:

public function testLoadFile ()
{
    $this->assertFalse(load_file('/some/non-existent/file'));
}

这问题我有的是,引发错误的原因我的单元的测试失败(因为它应该)。但是,如果我试图抓住它,或设置一个预期的例外,任何代码错误后从来没有触发执行所以我没法检测的回报价值的方法。

这个例子没工作:

public function testLoadFile ()
{
    $this->setExpectedException('Exception');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

任何想法如何能实现这一目标?

有帮助吗?

解决方案

没有办法在一个单元测试中做到这一点。如果您将测试返回值和通知分解为两个不同的测试,这是可能的。

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);
}

这还有一个额外的好处,那就是让你的测试更加清晰、干净和自记录。

关于:评论:这是一个很好的问题,直到我进行了几次测试之后我才知道。看起来好像会 不是 恢复默认/原始值,至少从 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;
}

关于:第二条评论:

这并不完全正确。我正在查看 PHPUnit 的错误处理程序,它的工作原理如下:

  • 如果它是一个 E_WARNING, , 使用 PHPUnit_Framework_Error_Warning 作为异常类。
  • 如果它是一个 E_NOTICE 或者 E_STRICT 错误,使用 PHPUnit_Framework_Error_Notice
  • 否则,使用 PHPUnit_Framework_Error 作为异常类。

所以,是的,错误 E_USER_* 没有转变成 PHPUnit 的 *_Warning 或 *_Notice 类,它们仍然转变成泛型 PHPUnit_Framework_Error 例外。

进一步的想法

虽然这完全取决于函数的使用方式,但如果是我,我可能会转而抛出实际的异常,而不是触发错误。是的,这会改变该方法的逻辑流程以及使用该方法的代码......现在,当无法读取文件时,执行不会停止。但这取决于您来决定所请求的文件是否确实不存在 异常的 行为。我更倾向于使用异常而不是错误/警告/通知,因为它们更容易处理、测试和融入您的应用程序流程。我通常会保留诸如折旧方法调用之类的通知。

其他提示

而不是在期待一个普通的"Exception"什么关于预期"PHPUnit_Framework_Error" ?

像这样的东西可能会做的事:

/**
 * @expectedException PHPUnit_Framework_Error
 */
public function testFailingInclude()
{
    include 'not_existing_file.php';
}

其中,我想,也可写为:

public function testLoadFile ()
{
    $this->setExpectedException('PHPUnit_Framework_Error');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

更多信息,请参阅 测试PHP错误
特别是,它说(报价):

PHPUnit_Framework_Error_NoticePHPUnit_Framework_Error_Warning 代表 PHP通知和警告,分别。


看着的/usr/share/php/PHPUnit/TextUI/TestRunner.php 文件我已在我的系统中,我看到这个 (线198和以下) :

if (!$arguments['convertNoticesToExceptions']) {
    PHPUnit_Framework_Error_Notice::$enabled = FALSE;
}

if (!$arguments['convertWarningsToExceptions']) {
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
}

所以也许你会必须通过一种参数,以激活的行为?但它似乎是默认...

实际上有测试两个返回值和抛出的异常(在这种情况下,由转换的PHPUnit的误差)的一种方式。

您只需要做到以下几点:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->assertFalse(@load_file('/some/non-existent/file'));

    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    load_file('/some/non-existent/file');
}

请注意,以测试你必须使用错误抑制操作的函数调用(函数名前@)的返回值。这种方式也不例外会被抛出,执行会继续。然后,你必须设置期望的异常像往常一样,以测试错误。

什么你不能做的是单元测试中测试多种异常。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top