How to execute code after trigger_error (..., E_USER_WARNING) in unit test (PHPUnit)?

I have a code like this:

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

and check this code:

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

I know how to test if an error is triggered ( $this->setExpectedException() ), but I do not know how to execute the code after the trigger_error() function.

Remember that in PHPUnit, E_USER_WARNING not converted to PHPUnit_Framework_Error_Warning (which can be disabled), but it is converted to PHPUnit_Framework_Error (which cannot be disabled).

+4
php unit-testing phpunit
source share
4 answers

This is one of those places where you are "officially" allowed to use the @ operator :)

Do one test to check the return value, another test to check if the warning is triggered. And by the way, I suggest you test if the warning was 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); } } 
+11
source share

What you should use is set_error_handler() ( link ) and restore_error_handler() , which allows you to set a function to handle this type of error. It also has an added bonus, giving you a place to check for alerts 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, suppressing errors is not a good idea :)

+3
source share

The answer is that in PHPUnit 3.4.15 there is a class PHPUnit_Util_ErrorHandler with the handleError method, which is executed when any error occurs. For an error such as E_USER_* , this method always throws PHPUnit_Framework_Error , so the rest of the code stops execution.

The only way to prevent this is to disable user error reporting, I think. This can be done as follows:

 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); } }
+2
source share

After almost 9 years, this question still arises regularly.

You can use Netsilik / BaseTestCase (MIT license) to get advanced functionality to acknowledge errors / warnings that run as expected:

composer require netsilik/base-test-case


Testing for 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'); } } 
0
source share

All Articles