phpunit您无法序列化或反序列化PDO实例

时间:2018-05-10 16:02:18

标签: phpunit

我正在使用PHPUnit和processIsolation =“true”因为我需要在我正在测试的代码中设置cookie值,并且没有processIsolation =“true”就无法完成。但在我的一个测试案例中,我收到了错误:

PHPUnit_Framework_Exception: [10-May-2018 15:23:28 UTC] PHP Fatal error:  Uncaught PDOException: You cannot serialize or unserialize PDO instances in -:394
Stack trace:
#0 [internal function]: PDO->__sleep()
#1 -(394): serialize(Array)
#2 -(536): __phpunit_run_isolated_test()
#3 {main}
  thrown in - on line 394

测试用例:

public function testUserCookieIsSavedToClicksTable()
{
    $cookie = sha1('12345');
    $_COOKIE['user_cookie'] = $cookie;
    $offerId = 1;
    $tx = $this->getTx($offerId);

    // Go
    $this->controller = new ClickController(new Click(new Database(Cache::getInstance()), new Queue, new RedisStorage()));
    $this->runLocal([1, $this->userId], null);

    $sql = 'select * from clicks order by id desc limit 1';
    $click = $this->db->query($sql, [], 'fetch');
    $this->assertEquals($tx, $click['tx_id']);
    $this->assertEquals($click['user_cookie'], $cookie);
}

调用$this->assertEquals($tx, $click['tx_id']);$this->assertEquals($click['user_cookie'], $cookie);中的任何一个时会抛出此错误。但我可以var_dump在这些断言中使用的任何变量。

我尝试了here的所有解决方案,但它们不适合我

2 个答案:

答案 0 :(得分:2)

进程隔离要求隔离进程中的所有对象都可以序列化/反序列化。

您看到的错误是关于不支持PHP对象序列化/反序列化的特定对象。

首先,在您询问的情况下,您不能在该测试中使用进程隔离。

如果你稍微咀嚼一下并改变一些关于这里发生了什么的想法以及为什么某些对象(如数据库连接)通常无法序列化,那么为什么进程隔离也可能会使用序列化,也许我想到为什么数据库连接的进程隔离毕竟不是一个好主意。

因此,尽管您在此处看到了导致错误的技术限制,但最后我还是说,不要在隔离的进程中运行基于数据库连接的测试作为相同测试套件的一部分。

这可能不是你所希望的答案。

也许分而治之可以在这里有意义:将那些过程隔离工作的测试放入它自己的测试套件中并为其配置过程隔离。

对于另一个人也做同样的自己的测试工具。

PHPUnit XML配置文件提供了进行这些设置的设置,有时甚至需要具有多个这些XML配置文件,这取决于所使用的Phpunit版本,还取决于测试运行器的配置设置。

答案 1 :(得分:1)

这可能是您db组件中的错误。它应该实现__sleep()方法以确保PDO实例未使用它进行序列化(并且可能在反序列化后实现__wakeup()重新连接)。

您没有分享有关db组件的任何信息,但这可以通过以下方式实现:

public function __sleep() {
    $fields = (array) $this;
    unset($fields['pdo']);
    return array_keys($fields);
}