2
votes

I'm using PHPUnit with processIsolation="true" because I need to set cookie value in the code I'm testing, and without processIsolation="true" it can't be done. But in one of my test case, I'm getting the error:

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

Test case:

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 error is thrown when calling any of $this->assertEquals($tx, $click['tx_id']); or $this->assertEquals($click['user_cookie'], $cookie);. But I can var_dump any variables used in those assertions.

I tried all solutions from here but they not working for me

2

2 Answers

2
votes

Process Isolation require that all objects in the process to isolate can be serialized / unserialized.

The error you see is about a specific object that does not support PHP object serialization / unserialization.

That first of all means in the case you ask about, that you can not make use of process isolation for that test.

If you chew on that a bit and change some thoughts about what is going on here and why some objects (like database connections) normally can not be serialized and then as well, why process isolation might make use of serialization as well, it perhaps comes to mind as well why process isolation for database connections is not such a good idea after all.

So even though you see a technical limitation here that is causing the error, in the end I'd say it makes perfect sense to not run database connection based tests in isolated processes as part of the same testsuite.

This is perhaps not the answer you hoped for.

Perhaps divide and conquer can make sense here: Put those tests for which process isolation work into a testsuite of it's own and configure process isolation for it.

For the other one do the same into a testsuite of their own as well.

The PHPUnit XML configuration file offers settings to make these, sometimes it is even needed to have multiple of these XML configuration files, depends a bit on the Phpunit version used, but also for configuration settings for the test-runner.

1
votes

This is probably error in your db component. It should implement __sleep() method to make sure, that PDO instance is not serialized with it (and probably implement __wakeup() to reconnect after deserialization).

You didn't share any informaction about db component, but this could be achieved by something like this:

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