6

我正在尝试在一个非常好的 IDE PhpStorm 中使用 setcookie() 函数进行一些单元测试。但我每次都会收到以下错误:

Cannot modify header information - headers already sent by (output started at /tmp/phpunit.php:418)

可能此错误的原因是在 setcookie() 调用之前使用 flush() print('some text') 。但是刷新是在 PhpStorm 生成的 /tmp/phpunit.php 文件中执行的。虽然 setcookie() 是从我的来源调用的。所以我不能编辑生成的文件来做某种输出缓冲。还有另一个时刻:PhpStorm 像这样执行 /tmp/phpunit.php 脚本:

/usr/bin/php /tmp/phpunit.php -config /var/www/.../protected/tests/phpunit.xml d /var/www/.../protected/tests/unit/user

请帮我解决这个问题。如何直接从 PhpStorm 运行单元测试?

4

4 回答 4

6

解决此问题的一种可能方法是使用“模拟”替换该setcookie()功能。

这是单元测试中的一种常用技术,您希望测试依赖于您不想影响当前测试的外部类或函数的东西。

这样做的方法是setcookie()在您的单元测试代码中创建一个存根函数定义。然后将在测试期间调用它而不是真正的setcookie()函数。究竟如何实现这个存根函数取决于您,并且取决于您的代码使用它的目的。

这种方法的主要问题是 PHP 不允许您默认覆盖现有函数 - 如果您在标准 PHP 安装上尝试此操作,您将收到“错误:函数无法重新声明”。

这个问题的解决方案是 PHP 的Runkit 扩展,它是专门为这种测试而设计的,它允许您重命名现有函数,包括内置函数。

如果您在测试环境中配置 PHP 安装以包含 Runkit 扩展,您将能够进行此类测试。

希望有帮助。

于 2011-03-29T10:22:51.397 回答
6

我找到了一个更简单的解决方案。考虑这个类:

class Cookie
{
    public function set($name, $value)
    {
        return setcookie($name, $value);
    }
}

测试将抛出问题中描述的错误,除非您设置注释@runInSeparateProcess

class CookieTest
{
    /**
     * @runInSeparateProcess
     */
    function test_set()
    {
        $cookie = new Cookie;
        $this->assertTrue($cookie->set('mycookie', 'myvalue');
    }
}
于 2017-04-27T18:25:36.573 回答
0

另一种解决方法,无需创建代理类并对其进行模拟,但需要更改工作代码级别。

function setTestableCookie(string $key, $value): void
{
    $_COOKIE[$key] = $value;

    if (headers_sent() === false) {
        setcookie(
          $key,
          $value,
          ... other cookie params ...
        );
    }
}

这样,它将在单元测试中工作并在生产代码上设置适当的 cookie 参数。

于 2020-06-24T09:25:39.803 回答
-2

而不是尝试设置实际的 cookie 标头(这将失败,因为内容已经发送);出于测试目的,您可以简单地显式设置 COOKIE 超全局:

$_COOKIE['mycookie']=myvalue';
于 2018-12-26T17:02:38.933 回答