【问题标题】:PHPUnit output causing Zend_Session exceptionsPHPUnit 输出导致 Zend_Session 异常
【发布时间】:2017-03-20 21:42:04
【问题描述】:

我遇到了很多类似这样的错误:

Zend_Session_Exception: Session must be started before any output has been sent to the browser; output started in /usr/local/zend/share/pear/PHPUnit/Util/Printer.php/173

在运行我的应用程序的测试套件时。这适用于 PHPUnit 3.5.10 和 PHP 5.3.5。

没有导致此问题的神秘、意外的空白输出。我已经确定“发送到浏览器的输出”是正在执行的 PHPUnit 测试的实际输出。如果我打开 PHPUnit/Util/Printer.php 并用 if (strpos($buffer, 'PHPUnit 3.5.10 by Sebastian Bergmann') === false) 包裹 print $buffer 行(有效地停止 PHPUnit 的第一行输出),那么我的第一个测试成功(直到测试用例输出一个点,指示测试成功,然后下一个测试失败,因为点已输出)。

我团队中的另一位开发人员能够成功运行完整的测试套件,所以我知道这不是应用程序代码的问题。一定是我的本地环境的一些配置设置或问题。

我已经检查了 php.ini 以确认 output_buffering 已打开,implicit_flush 已关闭,它们确实是。

我也尝试将 Zend_Session::$_unitTestEnabled = true; 添加到我的测试引导程序中,但这没有帮助(无论如何也不应该这样做,因为它可以在其他开发人员的机器上以及没有它的情况下在我们的 CI 服务器上运行)。

除了忽略错误还有什么建议吗?我从来没有见过这样的事情,真的很茫然。

谢谢!

更新:

为了进一步隔离问题,我通过执行以下测试脚本将 ZF 和我的应用程序排除在外:

<?php

class SessionTest extends PHPUnit_Framework_TestCase
{
    public function testSession()
    {
        session_start();
        $this->assertTrue(true);
    }
}

测试失败:

1) SessionTest::testSession
session_start(): Cannot send session cookie - headers already sent by (output started at /home/mmsa/test.php:1)

但是,完全相同的测试可以在朋友的机器上运行。 PHP 和 PHPUnit 版本相同。

【问题讨论】:

    标签: php zend-framework phpunit zend-session


    【解决方案1】:

    使用 -stderr 标志运行 phpunit,(新版本可能使用 --stderr 代替)例如

     phpunit -stderr mytest.php
     # or
     phpunit --stderr mytest.php
    

    这会将 phpunit 的输出定向到 stderr,防止它中断 HTTP 标头生成。

    测试可能在您朋友的机器上运行,因为他启用了输出缓冲(尽管我不确定这是否与 CLI 上下文相关)。

    【讨论】:

    • 忽略我之前的评论 - 这实际上确实有效。昨晚我试图解决这个问题时,PHPUnit 核心中仍有一些调试代码。当我恢复它时,--stderr 标志允许测试工作。谢谢!不过,这是一种解决方法。如果它可以在没有--stderr 标志的另一台机器上运行,那么它应该可以在我的机器上运行。据我所知,我没有禁用输出缓冲。我还能检查什么?
    • 在较新的版本中它可能是--stderr(这肯定会更标准),但我的(有点过时的)phpunit 安装只支持-stderr。由于这个会话问题,我们在运行所有测试时使用-stderr。至于您的环境之间可能有什么不同,我只能建议比较两台机器上php -i 的输出以找出配置差异。
    • 这也适用于我。不幸的是,(目前)似乎还没有为此输入phpunit.xml 的选项。
    • @dave1010 已经有修复了! github.com/sebastianbergmann/phpunit/issues/657
    • 在 4.6.4 版本上,它是 --stderr 和 THANKS 效果很好。我有几个需要设置 cookie 的函数,这使得测试它们成为可能。
    【解决方案2】:

    我认为更好的方法是使用

    Zend_Session::$_unitTestEnabled = true;
    

    在我的测试引导程序中使用它可以防止出现此错误。

    【讨论】:

      【解决方案3】:

      如果 PHPUnit 在你的系统上使用的 php 二进制文件是 CGI 而不是 CLI 版本,那么session_start 真的会尝试设置 cookie,你会得到那个错误。

      您可以通过调用 php_sapi_name 来确认您使用的是什么 SAPI。

      【讨论】:

      • echo php_sapi_name(); 输出“cli”
      • 我唯一要说的另一件事是确保pear config-show | grep php_bin 列出了您期望的相同二进制文件。
      • 它指向/usr/local/zend/bin/php,这是我环境中唯一安装的PHP。
      【解决方案4】:

      我在另一个项目中遇到了同样的问题,我发现问题是 PHPUnit 导致输出启动过早,因为它在运行测试之前输出了欢迎消息。

      将以下两行添加到bootstrap.php

      ini_set('session.use_cookies', 0);
      ini_set('session.cache_limiter', '');
      

      这应该可以防止在您的测试套件运行之前发送标头。

      【讨论】:

        【解决方案5】:

        就像Makor 说的,你只需要在你的bootstrap.php

        中添加这个
        Zend_Session::$_unitTestEnabled = true;
        

        就我而言,我在我的 bootstrap.php 文件中放了类似的东西

        if(APPLICATION_ENV == 'testing' && php_sapi_name() == 'cli') {
            Zend_Session::$_unitTestEnabled = true;
        }
        

        所以你不必再改变它了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-06
          • 2011-08-06
          • 2012-03-14
          • 2019-06-18
          相关资源
          最近更新 更多