【问题标题】:Cannot send session cookie - headers already sent PHPUnit / Laravel无法发送会话 cookie - 标头已发送 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)

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

【问题讨论】:

标签: php unit-testing laravel-4 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://stackoverflow.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), '/');
}

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

【讨论】:

    猜你喜欢
    • 2013-05-15
    • 2013-04-25
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2017-08-29
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多