sebastianbergmann / phpunit

The PHP Unit Testing framework.
https://phpunit.de/
BSD 3-Clause "New" or "Revised" License
19.65k stars 2.2k forks source link

Passing Exception instance via DataProvider throws ReflectionException #4347

Open stemis opened 4 years ago

stemis commented 4 years ago
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()],
        ];
    }
}
epdenouden commented 4 years ago

@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 commented 4 years ago

@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

epdenouden commented 4 years ago

@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).

MasonM commented 3 years ago

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.

cmath10 commented 2 years ago

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   
underground20 commented 1 year ago

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

websitevirtuoso commented 8 months ago

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

kubawerlos commented 19 hours ago

As PHPUnit only supports >= PHP 8.1, can this be closed as only occurs when using PHP 7.4?