![]() |
(from https://github.com/sebastianbergmann/phpunit/issues/720#issuecomment-10399612) |
And rightfully so. Headers are essentially global state, which is hard to unit test. However, if you're willing to install the PECL extension Runkit, you can actually unit test headers if you really want to.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Class that tries to send a header. | |
*/ | |
class SendsHeaders { | |
/** | |
* Send a header to the user's browser. | |
*/ | |
public function sendHeader() { | |
header('This is a header', true, 400); | |
} | |
} | |
/** | |
* Unit tests for SendHeaders class. | |
*/ | |
class SendsHeadersTest extends PHPUnit_Framework_TestCase { | |
/** | |
* Array of headers that have been sent. | |
* @var array | |
*/ | |
public static $headers; | |
/** | |
* Subject under test. | |
* @var SendsHeaders | |
*/ | |
protected $sendsHeaders; | |
/** | |
* Use runkit to create a new header function. | |
*/ | |
public static function setUpBeforeClass() { | |
if (!extension_loaded('runkit')) { | |
return; | |
} | |
// First backup the real header function so we can restore it. | |
runkit_function_rename('header', 'header_old'); | |
// Now, create a new header function that makes things testable. | |
runkit_function_add( | |
'header', | |
'$string,$replace=true,$http_response_code=null', | |
'SendsHeadersTest::$headers[] = array($string,$replace,$http_response_code);' | |
); | |
} | |
/** | |
* After we're done testing, restore the header function. | |
*/ | |
public static function tearDownAfterClass() { | |
if (!extension_loaded('runkit')) { | |
return; | |
} | |
// Get rid of our new header function. | |
runkit_function_remove('header'); | |
// Move our backup to restore header to its original glory. | |
runkit_function_rename('header_old', 'header'); | |
} | |
/** | |
* Set up our subject under test and global header state. | |
*/ | |
protected function setUp() { | |
$this->sendsHeaders = new SendsHeaders(); | |
self::$headers = array(); | |
} | |
/** | |
* Unit test sending a header. | |
* @requires extension runkit | |
* @test | |
*/ | |
public function testSendHeader() { | |
$expectedHeaders = array( | |
array('This is a header', true, 400), | |
); | |
$this->sendsHeaders->sendHeader(); | |
$this->assertEquals($expectedHeaders, self::$headers); | |
} | |
} |
I've had a similar issue in the past. If I recall the "official" answer from a PHPUnit bug ticket was to batch up your headers to send in an array/property/Response object, and then test the contents of that. It still relies on PHP knowing how to send a header correctly, but you don't open up the can of runkit worms. There are a few more helpful comments here too:
ReplyDeletehttp://www.brianfenton.us/2011/01/unit-testing-with-phpunit.html