Passing Exception instance via DataProvider throws ReflectionException
| Q | A |
|---|---|
| PHPUnit version | 9.2.5 |
| PHP version | PHP 7.4.7 (cli) (built: Jun 11 2020 18:33:07) ( NTS ) |
| Installation Method | Composer |
Summary
When passing an Exception instance via a dataProvider, an Uncaught ReflectionException is thrown:
Current behavior
Fatal error: Uncaught Exception: Serialization of 'ReflectionClass' is not allowed in /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:723
Stack trace:
#0 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php(723): serialize(Array)
#1 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php(638): PHPUnit\Framework\TestCase->run(Object(PHPUnit\Framework\TestResult))
#2 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php(638): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#3 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php(638): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#4 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php(638): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#5 /var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(657): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#6 /var/www/html/vendor/phpunit/phpunit/src/TextUI/Command in /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php on line 723
How to reproduce
processIsolation="true"
class MyTest extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider thisMethodDataProvider
*/
public function testThisMethod(\Exception $expectedException): void
{
// ...
}
public function thisMethodDataProvider()
{
return [
[new \Exception()],
];
}
}
@stemis Quick check: you are running the tests in a seperate process, is that correct?
In order to pass the provided data from the orchestrating PHPUnit process to the isolated one it uses [un]serialize($data).
@sebastianbergmann Is this a known limitation and expected behaviour?
@stemis Quick check: you are running the tests in a seperate process, is that correct? In order to pass the provided data from the orchestrating PHPUnit process to the isolated one it uses
[un]serialize($data).
Yes this only happens with processIsolation turned on
@stemis Thanks for the additional information. Passing data around using serialization should only be used for external processes including PHPT files. ~With the upcoming @dataProvider refactoring I'd like to know what's going on here. See what's @sebastianbergmann knows about the intended behaviour.~
Ah! Thanks for the patch notes to your update :) I would be great if there would be a way to pass any data type between processes. Will discuss this, perhaps I can stick a fork in this mechanism while refactoring the data provider load-run-unload cycle.
Thanks for bringing this to my attention. I will reply here sometime next week when working on #4302 (main loop refactoring) and #3736 (data provider resource management).
I can confirm this bug on PHPUnit 9.5.1. However, this only seems to happen with PHP 7.4. I can't reproduce this with PHP 7.3, so I think something changed in 7.4.
Hello! Got this bug on phpunit 8.5.0, php 7.4
PHP Fatal error: Uncaught Exception: Serialization of 'ReflectionClass' is
not allowed in /var/www/crm/vendor/phpunit/phpunit/src/Framework/TestCase.
php:772
Stack trace:
#0 /var/www/crm/vendor/phpunit/phpunit/src/Framework/TestCase.php(772): ser
ialize(Array)
#1 /var/www/crm/vendor/phpunit/phpunit/src/Framework/TestSuite.php(627): PH
PUnit\Framework\TestCase->run(Object(PHPUnit\Framework\TestResult))
#2 /var/www/crm/vendor/phpunit/phpunit/src/Framework/TestSuite.php(627): PH
PUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#3 /var/www/crm/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(656): PHPU
nit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#4 /var/www/crm/vendor/phpunit/phpunit/src/TextUI/Command.php(235): PHPUnit
\TextUI\TestRunner->doRun(Object(PHPUnit\Framework\TestSuite), Array, Array
, true)
#5 /var/www/crm/vendor/phpunit/phpunit/src/TextUI/Command.php(194): PHPUnit
\TextUI\Command->run(Array, true)
#6 /var/www/crm/vendor/phpunit/phpunit/phpunit(92): PHPUnit\TextUI\Command:
:main()
#7 in /var/www/crm/vendor/phpunit/phpunit/src/Framework/TestCase.php on li
ne 772
Hello! Got this bug on phpunit 9.5.10, php 7.4
Exit Code: 2(Misuse of shell builtins)
Output:
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.
...ESerialization of 'ReflectionClass' is not allowed
I have the same bug when migrate laravel project from php8.2 to php 8.3 phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
backupGlobals="false"
bootstrap="vendor/autoload.php"
colors="true"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
processIsolation="false"
stopOnFailure="false"
executionOrder="defects"
>
<testsuites>
<!-- <testsuite name="Unit">-->
<!-- <directory suffix="Test.php">./tests/Unit</directory>-->
<!-- </testsuite>-->
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="Modules">
<directory suffix="Test.php">./app/Modules/*/Tests/Commands</directory>
<directory suffix="Test.php">./app/Modules/*/Tests/Feature</directory>
<directory suffix="Test.php">./app/Modules/*/Tests/Unit</directory>
</testsuite>
</testsuites>
<coverage/>
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
<source>
<include>
<directory suffix=".php">./app</directory>
</include>
</source>
</phpunit>
parameter processIsolation to false to make tests run on 8.3 if I set to "true" all tests fails parameter processIsolation to true to make tests run on 8.2
If you need more info please let me know and I will be happy to give more details
My composer file in case it is important
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"php": "^8.3",
"ext-simplexml": "*",
"aaronfrancis/pulse-outdated": "^0.1.2",
"bensampo/laravel-enum": "^v6.7.0",
"deployer/deployer": "^v7.3.3",
"google/recaptcha": "^1.3.0",
"guzzlehttp/guzzle": "^7.8.0",
"halaxa/json-machine": "^1.1.4",
"intervention/image": "^2.7.2",
"laravel/framework": "^v10.38.2",
"laravel/horizon": "^v5.21.4",
"laravel/pulse": "^v1.0.0-beta7",
"laravel/scout": "^v10.6.0",
"laravel/telescope": "^v4.17.3",
"laravel/tinker": "^v2.8.2",
"maatwebsite/excel": "^3.1.51",
"milwad/laravel-validate": "^1.7.2",
"nwidart/laravel-modules": "^v10.0.2",
"php-open-source-saver/jwt-auth": "^2.1.0",
"pusher/pusher-php-server": "^7.2.4",
"rebing/graphql-laravel": "^9.1.0",
"santigarcor/laratrust": "^8.2.1",
"sentry/sentry-laravel": "^4.1.1",
"spatie/laravel-activitylog": "^4.7.3",
"spatie/laravel-medialibrary": "^10.15.0",
"spatie/laravel-sitemap": "^7.0.0",
"teamtnt/laravel-scout-tntsearch-driver": "v13.2.0",
"toin0u/geocoder-laravel": "^4.6.0"
},
"require-dev": {
"ext-json": "*",
"barryvdh/laravel-ide-helper": "^v2.13.0",
"brianium/paratest": "^7.3",
"doctrine/dbal": "^3.7.2",
"fakerphp/faker": "^v1.23.0",
"itsgoingd/clockwork": "^5.1",
"laracasts/cypress": "^3.0.1",
"larastan/larastan": "^v2.7.0",
"marvinrabe/laravel-graphql-test": "^0.4.1",
"mockery/mockery": "^1.6.7",
"nunomaduro/collision": "^v7.10.0",
"phpunit/phpunit": "^10.5.3",
"roave/security-advisories": "dev-latest",
"spatie/laravel-ignition": "^2.3.3"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"@php artisan ide-helper:generate",
"@php artisan ide-helper:meta"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
},
"extra": {
"laravel": {
"dont-discover": [
]
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": true
}
},
"minimum-stability": "beta",
"prefer-stable": true
}
I tried to use native lib ./phpunit.phar instead of composer and still have problem with isolation