【问题标题】:How to execute code after trigger_error(..., E_USER_WARNING) in unit test (PHPUnit)?如何在单元测试(PHPUnit)中 trigger_error(..., E_USER_WARNING) 之后执行代码?
【发布时间】:2010-09-24 10:18:14
【问题描述】:

我有这样的代码:

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(不能禁用)。

【问题讨论】:

    标签: php unit-testing phpunit


    【解决方案1】:

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

    做一个测试来检查返回值,另一个测试来检查警告是否被触发。顺便说一句,我建议你测试是否触发了警告。

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

    【讨论】:

    • 感谢您的回答。使用 @ 字符看起来确实是一个很好的例子。 :)
    • 这仍然被认为是测试E_USER_WARNING的正确方法吗?
    • @tereško 是的。这仍然是我知道这样做的唯一有点理智的方式。 首先 测试警告然后测试错误可能是有意义的,因此在 E_FATALs 的情况下,错误抑制关闭。但是xdebug.scream 也总是在那里 :)
    • @BobStein-VisiBone 谢谢。非常感谢
    • php.net 文档:Error Control Operators PHP 支持一种错误控制运算符:at 符号 (@)。当附加到 PHP 中的表达式时,该表达式可能生成的任何错误消息都将被忽略。
    【解决方案2】:

    您应该使用的是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);
       }
    
    }
    

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

    【讨论】:

      【解决方案3】:

      答案是在 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); } }

      【讨论】:

        【解决方案4】:

        将近 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');
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-02-11
          • 2012-02-26
          • 1970-01-01
          • 2022-07-06
          • 1970-01-01
          • 1970-01-01
          • 2015-03-20
          • 1970-01-01
          • 2021-09-11
          相关资源
          最近更新 更多