如何在单元测试(PHPUnit)中的trigger_error(...,E_USER_WARNING)之后执行代码?

时间:2010-09-24 10:18:14

标签: php unit-testing phpunit

我有这样的代码:

class ToBeTested
{
  function simpleMethod($param)
  {
    if(0 === $param)
    {
      trigger_error("Param is 0!", E_USER_WARNING);
      return false;
    }

    return true;
  }
}

并测试此代码:

class SimpleTest extends PHPUnit_Framework_TestCase
{
   function testSimpleMethod()
   {
     $toBeTestedObject = new ToBeTested();
     $this->assertFalse($toBeTestedObject->simpleMethod(0));
   }
}

我知道如何测试,如果错误被触发($this->setExpectedException()),但我不知道如何在trigger_error()函数之后执行代码。

请记住,在PHPUnit中,E_USER_WARNING未转换为PHPUnit_Framework_Error_Warning(可以禁用),但会转换为PHPUnit_Framework_Error(无法禁用)。

4 个答案:

答案 0 :(得分:11)

这是“官方”允许使用@运算符的地方之一:)

进行一项测试以检查返回值,另一项测试用于检查警告是否被触发。顺便说一句,如果触发警告,我建议你测试。

class SimpleTest extends PHPUnit_Framework_TestCase
{
   function testSimpleMethodReturnValue()
   {
     $toBeTestedObject = new ToBeTested();
     $this->assertFalse(@$toBeTestedObject->simpleMethod(0));
   }

   /**
    * @expectedException PHPUnit_Framework_Error
    */
   function testSimpleMethodEmitsWarning() {
     $toBeTestedObject = new ToBeTested();
     $toBeTestedObject->simpleMethod(0);
   }
}

答案 1 :(得分:3)

您应该使用的是set_error_handler()link)和restore_error_handler(),它可以让您设置一个函数来处理给定类型的错误。它还有一个额外的好处,就是让你有机会同时测试警告。

所以,像这样:

class SimpleTest extends PHPUnit_Framework_TestCase
{
   function testSimpleMethod()
   {
     set_error_handler(array($this, '_handleWarnedMethod'), E_USER_WARNING);

     $toBeTestedObject = new ToBeTested();
     $this->assertFalse($toBeTestedObject->simpleMethod(0));

     restore_error_handler();
   }

   private function _handleWarnedMethod($errno, $errstr)
   {
      $this->assertEquals(E_USER_WARNING, $errno);
      $this->assertEquals('Param is 0!', $errstr);
   }

}

与往常一样,错误抑制不是最好的主意:)

答案 2 :(得分:2)

答案是,在PHPUnit 3.4.15中,PHPUnit_Util_ErrorHandler类具有handleError方法,该方法在发生任何错误时执行。对于像E_USER_*这样的错误,此方法始终抛出PHPUnit_Framework_Error,因此停止执行其余代码。

我认为,防止这种情况的唯一方法是禁用用户错误报告。可以这样做:


class SimpleTest extends PHPUnit_Framework_TestCase
{
   function testSimpleMethod()
   {
      $toBeTestedObject = new ToBeTested();
// disable user errors reporting $oldReportingLevel = error_reporting(); error_reporting($oldReportingLevel ^ (E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE));
// check the condition $this->assertFalse($toBeTestedObject->simpleMethod(0));
// recover old error reporting level error_reporting($oldReportingLevel); } }

答案 3 :(得分:0)

近9年后,这个问题仍然经常出现。

您可以使用Netsilik/BaseTestCase(MIT许可证)来获得扩展的功能,以断言错误/警告将按预期方式触发:

composer require netsilik/base-test-case


测试E_WARNING

<?php
namespace Tests;

class MyTestCase extends \Netsilik\Testing\BaseTestCase
{
    /**
     * {@inheritDoc}
     */
    public function __construct($name = null, array $data = [], $dataName = '')
    {
        parent::__construct($name, $data, $dataName);

        $this->_convertNoticesToExceptions  = false;
        $this->_convertWarningsToExceptions = false;
        $this->_convertErrorsToExceptions   = true;
    }

    public function test_whenWarningTriggered_weCanTestForIt()
    {
        $foo = new Foo();
        $foo->bar();

        self::assertErrorTriggered(E_WARNING, 'The warning string');
    }
}