Тестирование заголовков PHP с помощью PHPUnit
Я пытаюсь использовать PHPUnit для тестирования класса, который выводит некоторые пользовательские заголовки.
проблема в том, что на моей машине это:
<?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);
}
}
или даже так:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
возвращает эту ошибку:
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.
Это выглядит так, как будто есть что-то еще, выводимое на терминал до запуска теста, даже если нет другого включенного файла и нет другого символа до начала тега PHP. Может быть, это что-то внутри PHPunit это и есть причина?
в чем может быть проблема?
6 ответов
проблема в том, что PHPUnit будет печатать заголовок на экране, и в этот момент Вы не можете добавить больше заголовков.
работа вокруг состоит в том, чтобы запустить тест в изолированном процессе. Вот пример
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
/**
* @runInSeparateProcess
*/
public function testBar()
{
header('Location : http://foo.com');
}
}
в результате:
$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.
.
Time: 1 second, Memory: 9.00Mb
OK (1 test, 0 assertions)
ключ является аннотацией @runInSeparateProcess.
если вы используете PHPUnit ~4.1 или что-то еще и получаете ошибку:
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
попробуйте добавить это в файл начальной загрузки, чтобы исправить это:
<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}
хотя выполнение теста в отдельном процессе устраняет проблему, при выполнении большого набора тестов возникают заметные накладные расходы.
мое исправление состояло в том, чтобы направить вывод phpunit в stderr, например:
phpunit --stderr <options>
это должно устранить проблему, а также означает, что вам не нужно создавать функцию-оболочку и заменять все вхождения в коде.
в сторону: для меня headers_list()
возвращалась 0 элементов. Я заметил @titelкомментарий на вопрос и решил, что он заслуживает особого упоминания здесь:
просто хотел покрыть это, если есть некоторые другие люди, заинтересованные и в этом тоже.
headers_list()
не работает при запуске PHPunit (который использует PHP CLI) ноxdebug_get_headers()
вместо работы.
HTH
у меня было более радикальное решение, чтобы использовать $_SESSION
внутри проверено/входит файлы.
Я отредактировал один из PHPUnit файлы ../ PHPUnit/Utils / Принтер.в PHP иметь "session_start();"
до команда "print $buffer".
это сработало для меня как шарм. Но я думаю, что решение пользователя "joonty" является лучшим из всех до сих пор.
Как уже упоминалось в комментарии, я думаю, что это лучшее решение для определения processIsolation в файле конфигурации XML, как
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
processIsolation = "true"
// ...
>
</phpunit>
таким образом, вам не нужно передавать параметр --stderr, который может раздражать ваших коллег.
альтернативным решением @runInSeparateProcess является указание параметра -- process-isolation при запуске PHPUnit:
name@host [~/test]# phpunit --process-isolation HeadersTest.php
это аналогично установке параметра processIsolation= "true" в phpunit.XML.
это решение имеет аналогичные преимущества / недостатки для указания параметра --stderr, который, однако, не работал в моем случае. В основном никаких изменений кода не требуется, даже если может быть хит производительности из-за запуска каждого теста в отдельном PHP процесс.