I am trying to write an integration test for an extension (app) for nextcloud. Nextcloud itself is based on Symfony. Long story short, I ended so far with a test class, that throws the following error message:
PHPUnit 8.5.15 by Sebastian Bergmann and contributors.
IE 2 / 2 (100%)
Time: 642 ms, Memory: 24.00 MB
There was 1 error:
1) tests\Integration\Setup\Migrations\Version000000Date20210701093123Test::testRedundantEntriesInDB with data set "caseC" (array(), array('bob'))
PHPUnit\Framework\Exception: PHP Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in Standard input code:340
Stack trace:
#0 Standard input code(340): serialize(Array)
#1 Standard input code(1237): __phpunit_run_isolated_test()
#2 {main}
thrown in Standard input code on line 340
ERRORS!
Tests: 2, Assertions: 1, Errors: 1, Incomplete: 1.
I tried to find the culprit for this error and as far as I can understand this is due to the fact that I am using @runInSeparateProcess
as an annotation to the named test and some global state seems to be existing that PHPUnit tries to save/serialize for the child PHP process.
The simplified MWE code is available in a branch on github or below for later reference. I tried to narrow down the problem after reading Symfony 2 + Doctrine 2 + PHPUnit 3.5: Serialization of closure exception and similar questions here. The created container is some sort of global storage that will hold all kinds of instances for the dependency injection method.
How can I avoid that PHPUnit tries to preserve this state? In fact, I use the process separation to have a clean starting environment for the tests.
What surprises me a bit is that the error only manifests when the second function parameter from the data provider is a non-empty array.
If required, it is possible to clone the repo and build some docker containers (under Linux, IDK about Windows) to run the test manually. Just go to .github/actions/run-tests
and call ./run-locally.sh --prepare stable21
to build the nvironment (take a big cup of coffee). Then the test can be started with ./run-locally.sh --run-integration-tests --filter 'tests\\Integration\\Setup\\Migrations\\Version000000Date20210701093123Test'
.
Here comes the basic MWE code:
<?php
namespace tests\Integration\Setup\Migrations;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use PHPUnit\Framework\TestCase;
class Version000000Date20210701093123Test extends TestCase {
/**
* @var IAppContainer
*/
private $container;
public function setUp(): void {
parent::setUp();
$app = new App('cookbook');
$this->container = $app->getContainer();
}
/**
* @dataProvider dataProvider
* @runInSeparateProcess
*/
public function testRedundantEntriesInDB($data, $updatedUsers) {
// print_r($updatedUsers);
sort($updatedUsers);
// print_r($updatedUsers);
$this->assertEquals($updatedUsers, []);
$this->markTestIncomplete('Not yet implemented');
}
public function dataProvider() {
return [
'caseB' => [
[
],
[],
],
'caseC' => [
[
],
['bob']
],
];
}
}