简体   繁体   English

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

[英]How to execute code after trigger_error(…, E_USER_WARNING) in unit test (PHPUnit)?

I have code like this: 我有这样的代码:

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

    return true;
  }
}

and test for this code: 并测试此代码:

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

I know how to test, if the error is triggered ( $this->setExpectedException() ), but I don't know how to execute the code after trigger_error() function. 我知道如何测试,如果错误被触发( $this->setExpectedException() ),但我不知道如何在trigger_error()函数之后执行代码。

Remember that in PHPUnit E_USER_WARNING is not converted into PHPUnit_Framework_Error_Warning (which can be disabled), but it is converted into PHPUnit_Framework_Error (which can't be disabled). 请记住,在PHPUnit中, E_USER_WARNING未转换为PHPUnit_Framework_Error_Warning (可以禁用),但它会转换为PHPUnit_Framework_Error (无法禁用)。

This is one of those places where you are 'officially' allowed to use the @ operator :) 这是“官方”允许使用@运算符的地方之一:)

Make one test to check the return value, another test to check if the warning gets triggered. 进行一次测试以检查返回值,另一次测试以检查警告是否被触发。 And by the way, I'd suggest you do test if the warning is triggered. 顺便说一句,我建议你试验,如果警报被触发。

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

What you should be using is set_error_handler() ( link ) and restore_error_handler() which lets you set a function to deal with errors of a given type. 你应该使用的是set_error_handler()link )和restore_error_handler() ,它允许你设置一个函数来处理给定类型的错误。 It also has the added bonus of giving you a place to test the warning at the same time. 它还有一个额外的好处,就是让你有机会同时测试警告。

So, something like this: 所以,像这样:

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

}

As always, error suppression isn't the best idea :) 一如既往,错误抑制不是最好的主意:)

The answer is that in PHPUnit 3.4.15 there is PHPUnit_Util_ErrorHandler class with handleError method which is executed when any error occurs. 答案是在PHPUnit 3.4.15中有PHPUnit_Util_ErrorHandler类,其中包含handleError方法,该方法在发生任何错误时执行。 For error like E_USER_* this method always throws PHPUnit_Framework_Error , so execution of the rest of code is stopped. 对于像E_USER_*这样的错误,此方法始终抛出PHPUnit_Framework_Error ,因此停止执行其余代码。

The only way to prevent this is to disable user errors reporting, I think. 我认为,防止这种情况的唯一方法是禁用用户错误报告。 It could be done like this: 可以这样做:


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

Nearly 9 years later, and this question still comes up regularly. 将近9年后,这个问题仍然定期出现。

You can use Netsilik/BaseTestCase (MIT License) to get extended functionality to assert errors/warnings are triggered as expected: 您可以使用Netsilik / BaseTestCase (MIT许可证)获取扩展功能以断言错误/警告按预期触发:

composer require netsilik/base-test-case


Testing for a E_WARNING : 测试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');
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM