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

发布于 2024-09-24 18:10:24 字数 752 浏览 1 评论 0原文

我有这样的代码:

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(无法禁用)禁用)。

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.

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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一萌ing 2024-10-01 18:10:24

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

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

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

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);
   }
}
一念一轮回 2024-10-01 18:10:24

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

}

一如既往,错误抑制不是最好的主意:)

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. 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 :)

鲸落 2024-10-01 18:10:24

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

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. For error like E_USER_* this method always throws PHPUnit_Framework_Error, so execution of the rest of code is stopped.

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

青衫负雪 2024-10-01 18:10:24

近九年过去了,这个问题仍然经常出现。

您可以使用 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');
    }
}

Nearly 9 years later, and this question still comes up regularly.

You can use Netsilik/BaseTestCase (MIT License) to get extended functionality to assert errors/warnings are triggered as expected:

composer require netsilik/base-test-case

Testing for a 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');
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文