我正在尝试使用一个非常好的IDE PhpStorm中的setcookie()函数进行一些单元测试。但我每次都会收到以下错误:
Cannot modify header information - headers already sent by (output started at /tmp/phpunit.php:418)
这个错误的原因可能是在setcookie()调用之前使用flush()打印('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运行单元测试?
答案 0 :(得分:6)
解决此问题的一种可能方法是使用{mock}替换setcookie()
函数。
这是单元测试中的常用技术,您希望测试依赖于您不希望影响当前测试的外部类或函数的内容。
执行此操作的方法是在单元测试代码中为setcookie()
创建存根函数定义。然后在测试期间调用它而不是真正的setcookie()
函数。具体如何实现此存根函数取决于您,并取决于您的代码使用它的目的。
这种方法的主要问题是PHP默认情况下不允许您覆盖现有函数 - 如果您在标准PHP安装上尝试此操作,则会出现“错误:函数无法重新声明”
此问题的解决方案是PHP的Runkit extension,它是为此类测试明确设计的,并允许您rename an existing function,包括内置的。{/ p>
如果在测试环境中配置PHP安装以包含Runkit扩展,则可以进行此类测试。
希望有所帮助。
答案 1 :(得分:3)
我找到了一个更简单的解决方案。考虑这个课程:
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');
}
}
答案 2 :(得分:0)
而不是尝试设置实际的cookie标头(由于内容已经发送而将失败);出于测试目的,您可以简单地显式设置COOKIE超全局变量:
$_COOKIE['mycookie']=myvalue';
答案 3 :(得分:0)
另一种解决方法,无需创建代理类并对其进行模拟,但需要在工作代码级别进行更改。
function setTestableCookie(string $key, $value): void
{
$_COOKIE[$key] = $value;
if (headers_sent() === false) {
setcookie(
$key,
$value,
... other cookie params ...
);
}
}
这样,它将在单元测试中工作,并在生产代码上设置适当的cookie参数。