Test PHP headers with PHPUnit
The issue is that PHPUnit will print a header to the screen and at that point you can't add more headers.
The work around is to run the test in an isolated process. Here is an example
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
/**
* @runInSeparateProcess
*/
public function testBar()
{
header('Location : http://foo.com');
}
}
This will result in:
$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.
.
Time: 1 second, Memory: 9.00Mb
OK (1 test, 0 assertions)
The key is the @runInSeparateProcess annotation.
If you are using PHPUnit ~4.1 or something and get the error:
PHP Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in -:378
Stack trace:
#0 {main}
thrown in - on line 378
Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378
Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378
Call Stack:
0.0013 582512 1. {main}() -:0
Try add this to your bootstrap file to fix it:
<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}
How to test for expected headers?
If you have xdebug installed you can use xdebug_get_headers() to get the headers. Then you can test them as needed.
$headers=xdebug_get_headers();
gets you an array which looks like...
array(
0 => "Content-type: text/html",
1 => ...
)
So you'll need to parse each header line to separate the header name from the value
Unit Testing with items that need to send headers
Well, your session manager is basically broken by design. To be able to test something, it must be possible to isolate it from side effects. Unfortunately, PHP is designed in such a way, that it encourages liberal use of global state (echo
, header
, exit
, session_start
etc. etc.).
The best thing you can do, is to isolate the side-effects in a component, that can be swapped at runtime. That way, your tests can use mocked objects, while the live code uses adapters, that have real side-effects. You'll find that this doesn't play well with singletons, which I presume you're using. So you'll have to use some other mechanism for getting shared objects distributed to your code. You can start with a static registry, but there are even better solutions if you don't mind a bit of learning.
If you can't do that, you always have the option of writing integration-tests. Eg. use the PHPUnit's equivalent of WebTestCase
.
Why does PHPUnit interfere with setting HTTP headers in this code?
The answer to your literal question "Why does PHPUnit interfere with setting HTTP headers in this code?" is given fairly clearly in the answer to Test PHP headers with PHPunit. PHP's header()
will fail with the Cannot modify header information
warning if anything has been written to stdout. When running your code via PHPUnit, content has been sent to stdout long before your code under test has been reached.
You noted a separate issue when using the @runInSeparateProcess
annotation to fork a clean PHP process for your test:
Unexpected non-MediaWiki exception encountered, of type "Exception", exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /usr/share/pear/PHPUnit/Util/GlobalState.php:354
By default PHPUnit attempts to backup all of the $GLOBALS
data before each test and restore it afterwards. MediaWikiTestCase turns this behavior off but it looks like your extension's tests are not. It seems likely that the configuration for your extension includes a closure and is causing the serialization failure. Adding a @backupGlobals disabled
annotation to your PHPUnit_Framework_TestCase
class should get you past this problem.
Header getting dropped in Laravel/PHPUnit Testing
Headers are the 3rd parameter not the 2nd.
Try changing you're PUT
request to be:
$content = $this->put('users/xsettings/0', [], ['HTTP_Authorization' => $token])->response->getContent();
Hope this helps!
Laravel 5.2 unit test set headers not working
If you want to make a GET call with Headers, you can use:
$this->get($url, $headers);
Example:
$this->get('/oauth', [ 'HTTP_X_API_KEY' => 'xxxx' ]);
Since you are making a GET request, your parameters can be included in the $url
.
Source
Related Topics
Fix Incorrectly Displayed Encoding on an HTML Document with PHP
How to Get User Timezone Using Jquery
Sort Multidimensional Array by Date Column, Then Use Other Column Values If Dates Are the Same
How to Make a Cascading Drop Down List in PHP Using Jquery
How to Download Large Files Through PHP Script
Good Error Handling with File_Get_Contents
How to Execute a Stored Procedure in PHP Using SQLsrv and "" Style Parameters
Why Is Calling a Function (Such as Strlen, Count etc) on a Referenced Value So Slow
JavaScript Function Post and Call PHP Script
Why Does This Return Resource Id #2
Php: Strtotime Is Returning False for a Future Date
How to Reverse Order Output of a MySQL Query
Adding a Namespace When Using Simplexmlelement
Is There a Built-In Function or Plugin to Handle Date Formatting in JavaScript