Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/242.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php @runinsepareprocess时出现取消序列化错误_Php_Phpunit - Fatal编程技术网

Php @runinsepareprocess时出现取消序列化错误

Php @runinsepareprocess时出现取消序列化错误,php,phpunit,Php,Phpunit,我正在实现一个模块,该模块将提供一个用于处理和管理PHP会话的API。我正在测试允许用户启动会话、设置ID、获取ID、销毁会话等的Session\Manager实现。我正在使用PHPUnit的@runinsepareprocess注释,在单独的过程中测试此类中的方法。使用此注释时,由于非序列化错误,PHPUnit引发异常。当我不使用注释时,测试按预期运行,并在null不等于false时失败 这是导致错误的测试。到目前为止还没有实现细节,接口的所有方法都存在,但不执行任何操作 class Mana

我正在实现一个模块,该模块将提供一个用于处理和管理PHP会话的API。我正在测试允许用户启动会话、设置ID、获取ID、销毁会话等的
Session\Manager
实现。我正在使用PHPUnit的
@runinsepareprocess
注释,在单独的过程中测试此类中的方法。使用此注释时,由于非序列化错误,PHPUnit引发异常。当我不使用注释时,测试按预期运行,并在null不等于false时失败

这是导致错误的测试。到目前为止还没有实现细节,接口的所有方法都存在,但不执行任何操作

class ManagerTest扩展了phpunitestcase{
/**
*确保如果会话尚未启动,则会话存在
*方法返回false。
*
*@runinsepareprocess
*/
公共函数testsessionexistswhensessionhasnotbenstarted(){
$Manager=new\Session\Manager();
$this->assertFalse($Manager->sessionExists());
}
}
我能把问题归结到以下方法。我正在运行PHPUnit 3.7.5,调用的
runJob
方法是:

/**
*使用单独的PHP进程运行单个作业(PHP代码)。
*
*@param string$job
*@param PHPUnit_Framework_TestCase$test
*@param PHPUnit_Framework_TestResult$result
*@return数组| null
*@throws PHPUnit_Framework_异常
*/
公共函数runJob($job,PHPUnit\u Framework\u Test$Test=NULL,PHPUnit\u Framework\u TestResult$result=NULL)
{
$process=proc\U open(
$this->getPhpBinary(),
排列(
0=>数组('pipe','r'),
1=>数组('pipe','w'),
2=>数组('pipe','w')
),
$pipes
);
如果(!is_资源($process)){
抛出新的PHPUnit\u框架\u异常(
“无法为进程隔离创建进程。”
);
}
如果($result!==NULL){
$result->startTest($test);
}
$this->process($pipes[0],$job);
fclose($pipes[0]);
$stdout=stream\u get\u内容($pipes[1]);
fclose($pipes[1]);
$stderr=流内容($pipes[2]);
fclose($pipes[2]);
过程结束($过程);
$this->cleanup();
如果($result!==NULL){
$this->processChildResult($test,$result,$stdout,$stderr);
}否则{
返回数组('stdout'=>$stdout,'stderr'=>$stderr);
}
}
$stdout=stream\u get\u contents($pipes[1])
导致
$stdout
等于一个长字符串
。在
$this->processChildResult
中,
$stdout
中的值未序列化,传递给此函数的无效值触发警告,导致引发异常。我还能够确定
$this->getPhpBinary()
的返回值是
/usr/bin/php

引发异常消息:

PHPUnit_Framework_Exception: ???...???"*???...??


Caused by
ErrorException: unserialize(): Error at offset 0 of 10081 bytes
感谢hek2mgl,
$job
中的PHP代码可以查看。我创建了一个链接,因为这是一个相当多的代码,这个问题已经相当长了

我对这个特定领域的知识已经到了极限,不知道如何进一步调试这个问题。我不知道为什么
@runinsepareprocess
会失败,为什么运行单独进程的
$stdout
会导致一长串错误?标志。什么可能导致此问题?我如何着手解决此问题?由于未来的测试需要在一个单独的进程中运行,以确保启动和销毁的会话不会影响测试,因此我对该模块处于停顿状态

  • PHP:5.3.15
  • PHPUnit:3.7.5
  • IDE和命令行测试运行程序中导致的错误

  • PHPUnit\u Util\u PHP::runJob()
的$job参数是PHPUnit生成的PHP代码,它以一种可以作为命令行脚本执行的方式包装测试方法的代码(巧妙的技巧!)。 独立测试将把有关测试结果的序列化php数据输出回phpunit

如果要在pf
PHPUnit\u Util\u PHP::runJob()的顶部添加以下行,则可以研究此代码

再次执行失败的测试后,应在当前目录中创建文件
isolated.php
。您可以查看代码,您可以通过键入来执行它(在当前文件夹中)

php isolated.php
您是否看到任何看起来很混乱的输出


您还应该调试方法
PHPUnit\u Util\u PHP::processChildResult()
。该方法负责反序列化和检查测试结果。在那里放置一些echo或var_转储或使用调试器。当查看此方法时,问题很可能是由测试方法的非法输出引起的。

好的,我知道这里发生了什么,男孩,这是一个傻瓜

在测试期间,框架试图保持全局状态。在
PHPUnit\u Framework\u TestCase::run()
函数中,当前全局变量通过
PHPUnit\u Util\u GlobalState::getGlobalsAsString()
转换为PHP代码字符串。我目前正在使用自动加载库来处理需要适当的类文件的问题。该类在全局作用域中的变量中声明,导致将该对象的序列化放入由
getGlobalAssString()
创建的
$GLOBALS
数组中。无论出于何种原因,此序列化都包括空字节字符
\u0000
。当您尝试取消序列化时,会出现错误,并最终导致输出损坏

我通过在测试引导中创建一个函数修复了这个问题,该函数在全局范围之外创建自动加载对象。既然脚本不再尝试取消序列化空字节,那么脚本就不会产生错误,测试用例也会按预期工作。这
php isolated.php
class ManagerTest extends PHPUnit_Framework_TestCase {

    public function run(PHPUnit_Framework_TestResult $result = null) {
        $this->setPreserveGlobalState(false);
        parent::run($result);
    }

}