【问题标题】:phpunit You cannot serialize or unserialize PDO instancesphpunit 你不能序列化或反序列化 PDO 实例
【发布时间】:2018-05-14 06:32:02
【问题描述】:

我正在使用带有 processIsolation="true" 的 PHPUnit,因为我需要在我正在测试的代码中设置 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 的所有解决方案,但它们对我不起作用

【问题讨论】:

    标签: phpunit


    【解决方案1】:

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

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

    这首先意味着在您询问的情况下,您不能对该测试使用进程隔离。

    如果你仔细研究一下,并改变一些想法,了解这里发生了什么以及为什么某些对象(如数据库连接)通常不能被序列化,然后为什么进程隔离也可以使用序列化,或许我也会想到为什么数据库连接的进程隔离毕竟不是一个好主意。

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

    这也许不是你希望的答案。

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

    对于另一个人,也对他们自己的测试套件做同样的事情。

    PHPUnit XML 配置文件提供设置来进行这些设置,有时甚至需要拥有多个这些 XML 配置文件,这在一定程度上取决于所使用的 Phpunit 版本,但也用于测试运行器的配置设置。

    【讨论】:

    • 感谢您的回答,但还有另一个问题,我需要单独运行大部分甚至所有测试,因为我正在测试的逻辑是使用 cookie,而 phpunit 抛出错误 Cannot modify header information - headers already sent,所以我需要使用隔离(除非你知道另一种方式)但我也需要使用数据库连接:)所以我认为我不能在这里使用测试分离,我会尝试像@rob006 提到的那样序列化 Db 组件
    • 听起来更像是一个集成测试套件。如果这些测试都需要(隔离和cookies)似乎不是那么容易测试的代码。测试很容易揭示设计缺陷是很常见的,您可能会遇到这种情况(这本质上并不是一件坏事,只是说)。有时它有助于禁用会话的 cookie,例如,您也可以在 Phpunit XML 配置文件中控制 php ini 值。此外,如果有该错误消息,您也应该在其他问答条目中找到一些“灵感”,但我现在不能特别推荐一个具体的。
    【解决方案2】:

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

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

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

    【讨论】:

    • PDO 没有实现这些是有原因的,在实现这些之前理解推理是值得的(或者至少在想知道这个建议可能产生的后续问题时考虑它们)。没有规则没有例外,只是说。
    猜你喜欢
    • 2011-05-27
    • 2012-01-31
    • 2017-09-10
    • 2019-06-25
    • 2012-06-11
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多