Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test PHP headers with PHPUnit

I'm trying to use PHPunit to test a class that outputs some custom headers.

The problem is that on my machine this:

<?php  class HeadersTest extends PHPUnit_Framework_TestCase {      public function testHeaders()     {         ob_start();          header('Location: foo');         $headers_list = headers_list();         header_remove();          ob_clean();          $this->assertContains('Location: foo', $headers_list);     } } 

or even this:

<?php  class HeadersTest extends PHPUnit_Framework_TestCase {      public function testHeaders()     {         ob_start();          header('Location: foo');         header_remove();          ob_clean();     } } 

return this error:

name@host [~/test]# phpunit --verbose HeadersTest.php  PHPUnit 3.6.10 by Sebastian Bergmann.  E  Time: 0 seconds, Memory: 2.25Mb  There was 1 error:  1) HeadersTest::testHeaders Cannot modify header information - headers already sent by (output started at /usr/local/lib/php/PHPUnit/Util/Printer.php:173)  /test/HeadersTest.php:9  FAILURES! Tests: 1, Assertions: 0, Errors: 1. 

This looks as if there is something else outputting to the terminal before the test runs even though there is no other file included and there is no other character before the beginning of the PHP tag. Could it be something inside PHPunit that is causing this?

What could the issue be?

like image 333
titel Avatar asked Mar 16 '12 22:03

titel


2 Answers

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'); } 
like image 66
SamHennessy Avatar answered Sep 20 '22 06:09

SamHennessy


Although running the test in a separate process does fix the problem, there's a noticeable overhead when running a large suite of tests.

My fix was to direct phpunit's output to stderr, like so:

phpunit --stderr <options> 

That should fix the problem, and it also means that you don't have to create a wrapper function and replace all occurrences in your code.

like image 39
Jon Cairns Avatar answered Sep 23 '22 06:09

Jon Cairns