Pregunta Pruebe los encabezados de PHP con PHPUnit


Intento utilizar PHPunit para probar una clase que genera algunos encabezados personalizados.

El problema es que en mi máquina esto:

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

o incluso esto:

<?php

class HeadersTest extends PHPUnit_Framework_TestCase {

    public function testHeaders()
    {
        ob_start();

        header('Location: foo');
        header_remove();

        ob_clean();
    }
}

devuelve este 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.

Parece que hay algo más que se envía al terminal antes de que se ejecute la prueba, aunque no haya otro archivo incluido y no haya otro personaje antes del comienzo de la etiqueta PHP. ¿Podría ser algo dentro de PHPunit lo que está causando esto?

¿Cuál podría ser el problema?


75
2018-03-16 22:04


origen


Respuestas:


El problema es que PHPUnit imprimirá un encabezado en la pantalla y en ese punto no podrá agregar más encabezados.

El trabajo alrededor es ejecutar la prueba en un proceso aislado. Aquí hay un ejemplo

<?php

class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @runInSeparateProcess
     */
    public function testBar()
    {
        header('Location : http://foo.com');
    }
}

Esto dará como resultado:

$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

.

Time: 1 second, Memory: 9.00Mb

OK (1 test, 0 assertions)

La clave es la anotación @runInSeparateProcess.

Si está usando PHPUnit ~ 4.1 o algo similar, obtenga el 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

Intenta agregar esto a tu archivo bootstrap para solucionarlo:

<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
    define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}

103
2018-03-17 00:36



Aunque ejecutar la prueba en un proceso separado soluciona el problema, existe una sobrecarga considerable cuando se ejecuta un gran conjunto de pruebas.

Mi solución fue dirigir la salida de phpunit a stderr, así:

phpunit --stderr <options>

Eso debería solucionar el problema, y ​​también significa que no tiene que crear una función de envoltura y reemplazar todas las ocurrencias en su código.


92
2018-05-30 12:03



Como un aparte: Para mí headers_list() mantiene regresando 0 elementos. Me di cuenta @titelcomentó sobre la pregunta y supuso que merece una mención especial aquí:

Solo quería cubrir esto si hay otras personas interesadas   en esto también. headers_list() no funciona al ejecutar PHPunit   (que usa PHP CLI) pero xdebug_get_headers() funciona en cambio

HTH


7
2017-10-06 09:29



Tuve una solución más radical, para usar $_SESSION dentro de mi probado / incluido archivos. Edité uno de los PHPUnit archivos en ../PHPUnit/Utils/Printer.php tener un "session_start();" antes de comando "print $ buffer".

Me funcionó como un encanto. Pero creo que la solución del usuario "joonty" es la mejor de todas hasta ahora.


3
2017-11-09 13:12



Una solución alternativa a @runInSeparateProcess es especificar la opción --process-isolation cuando se ejecuta PHPUnit:

name@host [~/test]# phpunit --process-isolation HeadersTest.php

Eso es análogo a establecer la opción processIsolation = "true" en phpunit.xml.

Esta solución tiene ventajas / desventajas similares a la especificación de la opción --stderr, que sin embargo no funcionó en mi caso. Básicamente, no son necesarios cambios de código, aunque puede haber un golpe de rendimiento debido a la ejecución de cada prueba en un proceso separado de PHP.


0
2018-01-23 17:02



Como ya mencioné en un comentario, creo que es una mejor solución para definir processIsolation en el archivo de configuración XML como

     <?xml version="1.0" encoding="UTF-8"?>
     <phpunit
        processIsolation            = "true"
        // ... 
     >
     </phpunit>

De esta manera, no tiene que pasar la opción --stderr, lo que podría irritar a sus compañeros de trabajo.


0
2018-06-12 20:30