无法发送会话 cookie - 标头已发送 PHPUnit / Laravel

Posted

技术标签:

【中文标题】无法发送会话 cookie - 标头已发送 PHPUnit / Laravel【英文标题】:Cannot send session cookie - headers already sent PHPUnit / Laravel 【发布时间】:2014-06-09 20:12:03 【问题描述】:

当我在我的 TestCase 类上调用 parent::setUp() 对类进行单元测试时,我遇到了这个奇怪的问题 当我运行 phpunit 时,它会抛出这个错误:

1) MatchRequestRepositoryTest::test_find_requests_by_match_id ErrorException: session_start(): 无法发送会话 cookie - 标头 已经发送(输出开始于 /var/www/project.dev/vendor/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php:459)

可能是什么问题?感谢您的帮助。

【问题讨论】:

请检查:***.com/questions/8028957/… 你必须分享你的测试内容。此外,您的应用程序是否通过本机 session_ 函数调用或 Session:: 直接操作会话? Test PHP headers with PHPunit的可能重复 【参考方案1】:

在 PHPUnit 中处理此问题的一种方法是将输出发送到 stderr,而不是 stdout,如 this answer 所示。

phpunit --stderr

或者按照this comment 中的说明在您的phpunit.xml 中添加stderr="true"

【讨论】:

使用这个会不会适得其反?还是完全没有问题?谢谢 @Carlos 我还没有发现任何问题。 这应该是最好的答案! 我知道这是一个旧线程,但我对这个解决方案的问题是它没有为我的单元测试从phpunit.xml 生成junit.xml 文件。我猜是因为它输出到 stderr 而不是 stdout。 @xCHAN 这是一个有趣的警告!我从没想过这种副作用。如果您发现更好的选择,您应该发布解决方案并在您找到时联系我。【参考方案2】:

(更新:感谢 Louis Charette 的评论,这仅适用于 php 7.1 及更早版本(阅读错误报告,这听起来像是他们不打算修复的回归。因此,更好的解决方案是 Jeff Puckett 的( https://***.com/a/38045422/841830),将命令行上的 --stderr 标志提供给 phpunit。这会为您的代码保留标准输出,为 phpunit 保留标准错误,因此它们不会发生冲突。)


问题是你有一些代码,可能在你使用的框架深处,调用session_start()。反过来,它想要发送一个 cookie。但是 PHPUnit 已经开始将输出写入标准输出。

这里要理解的是,这只是一个单元测试,没有人关心标题。所以只需抑制错误消息。在不改变被测系统的情况下,您这样做的方式是在您自己的单元测试中调用 session_start() (在 parent::setUp() 之前或在该 setUp 函数内)。并使用 @ 前缀来抑制错误。例如

function setUp() 
  @session_start();
  parent::setUp();
  ...

【讨论】:

很遗憾,此解决方案仍会为您的测试产生错误。它将产生如下内容:There was 1 error: 1) Classname::ClassTest A session had already been started - ignoring session_start() @w00tland @ 应该停止报告任何错误或警告。你在抱怨的线上有@吗?添加/删除@ 是否会更改错误消息? (如果您无法让消息消失,那么可能值得提出一个新问题;这个问题是关于如何摆脱“已发送标头”的投诉。) 我知道它应该防止报告警告。我上面分享的消息是压制消息的结果。是的,如果我删除@,我会收到Cannot send session cookie - headers already sent by 消息。我有完全相同的问题;我只是想摆脱“标头已发送”的消息。 对于通过 Google 发现此问题的人,此修复程序可能会在 PHP 7.2 中产生与 session_set_save_handler 相关的另一组错误。请参阅:bugs.php.net/bug.php?id=75628Jeff Puckett 答案是与 PHP 7.2 更改相关的更好解决方案。 @LouisCharette 谢谢。我已经用该信息更新了答案。【参考方案3】:
 /**
 * @test
 * @runInSeparateProcess
 */
public function testName()
    //... your test

【讨论】:

请添加评论,解释您的答案。 @baikho 这段代码很容易解释。它允许测试在单独的进程中运行,因此 phpunit 尚未发送标头。【参考方案4】:

在 Laravel 中,我通过检查环境并避免“测试”环境的有问题的代码来避免这个问题。

// Code working in Laravel 4.2
if(App::environment() != 'testing') 
        // this will be skipped when testing
        setcookie('key', $val, time() + (86400 * 999), '/');

注意 - 警告:这意味着您无法测试这段代码!

【讨论】:

以上是关于无法发送会话 cookie - 标头已发送 PHPUnit / Laravel的主要内容,如果未能解决你的问题,请参考以下文章

无法发送会话缓存限制器 - 标头已发送 - CodeIgniter (Session.php)

无法发送会话缓存限制器-已发送的标头-CodeIgniter(Session.php)

警告:session_start() [function.session-start]:无法发送会话缓存限制器 - 标头已发送 [重复]

无法添加Cookie,已发送标头。 cron作业出错,但在浏览器中加载时无效

故障排除“警告:session_start():无法发送会话缓存限制器 - 标头已发送”

错误:在我初始化会话后发送标头后无法设置标头