Ну, Ваш менеджер сеансов в основном повреждается дизайном. Чтобы быть в состоянии протестировать что-то, должно быть возможно изолировать его от побочных эффектов. К сожалению, PHP разработан таким способом, что это поощряет свободное использование глобального состояния (echo
, header
, exit
, session_start
и т.д. и т.д.).
лучшая вещь, которую можно сделать, должен изолировать побочные эффекты в компоненте, который может быть подкачан во времени выполнения. Тем путем Ваши тесты могут использовать дразнившие объекты, в то время как живой код использует адаптеры, которые имеют реальные побочные эффекты. Вы найдете, что это не играет хорошо с одиночными элементами, которые я предполагаю, что Вы используете. Таким образом, необходимо будет использовать некоторый другой механизм для получения общих объектов, распределенных коду. Можно запустить со статического реестра, но существуют еще лучшие решения, если Вы не возражаете против небольшого количества изучения.
, Если Вы не можете сделать этого, у Вас всегда есть опция записи интеграционных тестов. Например, используйте эквивалент PHPUNIT WebTestCase
.
Я думаю, что "правильное" решение состоит в том, чтобы создать очень простой класс (настолько простой, оно не должно быть протестировано), это - обертка для связанных с сессией функций PHP, и используйте его вместо того, чтобы звонить session_start()
, и т.д. непосредственно.
В тесте передают фиктивный объект вместо реального непригодного для тестирования класса сессии с сохранением информации.
private function __construct(SessionWrapper $wrapper)
{
if (!$wrapper->headers_sent())
{
$wrapper->session_start();
$this->session_id = $wrapper->session_id();
}
}
Насколько я знаю, что Платформа Зенда использует ту же выходную буферизацию для их тестов пакета Zend_Session. Можно смотреть на их тестовые сценарии для запущения Вас.
Разве Вы не можете использовать вывод, буферизующий прежде, чем запустить тест? Если Вы буферизуете все, что производится, у Вас не должно быть проблем при установке любых заголовков, поскольку никакой вывод еще не будет отправлен клиенту в той точке.
, Даже если ОБЬ используется где-нибудь в Ваших классах, это является наращиваемым, и ОБЬ не должна влиять на то, что продолжается внутри.
Создайте файл начальной загрузки для phpunit, который вызывает:
session_start();
Затем запустите phpunit следующим образом:
phpunit --bootstrap pathToBootstrap.php --anotherSwitch /your/test/path/
Файл начальной загрузки вызывается раньше всего остального, поэтому заголовок не был отправлен и все должно работать нормально.
Создание файла начальной загрузки, указанное в 4 сообщениях назад, кажется самым простым способом решения этой проблемы.
Часто с PHP нам приходится поддерживать и пытаться добавить некую инженерную дисциплину к устаревшим проектам, которые ужасно скомпонованы. У нас нет времени (или полномочий), чтобы выбросить всю кучу мусора и начать заново, поэтому первый ответ troelskn не всегда возможен как путь вперед. (Если бы мы могли вернуться к первоначальному дизайну, то мы могли бы полностью отказаться от PHP и использовать что-нибудь более современное, например Ruby или Python, вместо того, чтобы помогать увековечивать этот COBOL в мире веб-разработки.)
Если вы пытаетесь напишите модульные тесты для модулей, которые используют session_start или setcookie повсюду, чем запуск сеанса в файле boostrap, чтобы решить эти проблемы.