From 461f7764e4c6f17dac49a1c4297611b10c6b7ac1 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Wed, 4 Aug 2021 19:24:14 +0000 Subject: [PATCH] Build/Test Tools: Use a custom autoloader for the PHPUnit 9.x mock object classes. This prevents the classes from being loaded automatically via the `autoload-dev` directives when a Composer-installed PHPUnit 5.x or 6.x version is used, as that would break the test run. It is expected that this autoloader will be removed soon, as it should no longer be needed when the PHPUnit version constraints are widened. Notes: * The autoloader file will be loaded from the Test bootstrap. * The autoloader will always be registered and directed to queue itself _before_ the Composer autoload file (which will already have been registered). * The autoloader will only actually load the WP copies of the files/classes when PHP 8.0 in combination with PHPUnit 7.x is detected. In all other cases, the autoloader will bow out, which effectively then defers to the Composer autoload file to load the files as shipped with the installed PHPUnit version. Follow-up to [48957], [49037], [51543]. Props jrf. See #47381. git-svn-id: https://develop.svn.wordpress.org/trunk@51544 602fd350-edb4-49c9-b593-d223f7449a82 --- composer.json | 14 ----- tests/phpunit/includes/bootstrap.php | 4 ++ .../includes/class-mockobject-autoload.php | 63 +++++++++++++++++++ 3 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 tests/phpunit/includes/class-mockobject-autoload.php diff --git a/composer.json b/composer.json index e7228a32ad..c753be2ab0 100644 --- a/composer.json +++ b/composer.json @@ -19,20 +19,6 @@ "phpcompatibility/phpcompatibility-wp": "~2.1.2", "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5" }, - "autoload-dev": { - "files": [ - "tests/phpunit/includes/phpunit7/MockObject/Builder/NamespaceMatch.php", - "tests/phpunit/includes/phpunit7/MockObject/Builder/ParametersMatch.php", - "tests/phpunit/includes/phpunit7/MockObject/InvocationMocker.php", - "tests/phpunit/includes/phpunit7/MockObject/MockMethod.php" - ], - "exclude-from-classmap": [ - "vendor/phpunit/phpunit/src/Framework/MockObject/Builder/NamespaceMatch.php", - "vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php", - "vendor/phpunit/phpunit/src/Framework/MockObject/InvocationMocker.php", - "vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php" - ] - }, "scripts": { "compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist --report=summary,source", "format": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf --report=summary,source", diff --git a/tests/phpunit/includes/bootstrap.php b/tests/phpunit/includes/bootstrap.php index 6419cd2890..160a7f7a4d 100644 --- a/tests/phpunit/includes/bootstrap.php +++ b/tests/phpunit/includes/bootstrap.php @@ -46,6 +46,10 @@ if ( version_compare( $phpunit_version, '5.7', '<' ) || version_compare( $phpuni exit( 1 ); } +// Register a custom autoloader for the PHPUnit 9.x Mockobject classes for compatibility with PHP 8.0. +require_once __DIR__ . '/class-mockobject-autoload.php'; +spl_autoload_register( 'MockObject_Autoload::load', true, true ); + // If running core tests, check if all the required PHP extensions are loaded before running the test suite. if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) { $required_extensions = array( diff --git a/tests/phpunit/includes/class-mockobject-autoload.php b/tests/phpunit/includes/class-mockobject-autoload.php new file mode 100644 index 0000000000..b8f46e8a2e --- /dev/null +++ b/tests/phpunit/includes/class-mockobject-autoload.php @@ -0,0 +1,63 @@ + true + */ + private static $supported_classes = array( + 'PHPUnit\Framework\MockObject\Builder\NamespaceMatch' => '/phpunit7/MockObject/Builder/NamespaceMatch.php', + 'PHPUnit\Framework\MockObject\Builder\ParametersMatch' => '/phpunit7/MockObject/Builder/ParametersMatch.php', + 'PHPUnit\Framework\MockObject\InvocationMocker' => '/phpunit7/MockObject/InvocationMocker.php', + 'PHPUnit\Framework\MockObject\MockMethod' => '/phpunit7/MockObject/MockMethod.php', + ); + + /** + * Loads a class. + * + * @param string $class_name The name of the class to load. + * @return bool + */ + public static function load( $class_name ) { + + if ( isset( self::$supported_classes[ $class_name ] ) === false ) { + // Bow out, not a class this autoloader handles. + return false; + } + + if ( PHP_VERSION_ID < 80000 ) { + // This autoloader is only needed when the tests are being run on PHP >= 8.0. + // Let the standard Composer autoloader handle things otherwise. + return false; + } + + if ( class_exists( 'PHPUnit\Runner\Version' ) === false // PHPUnit < 6.0. + || ( version_compare( \PHPUnit\Runner\Version::id(), '7.0.0', '<' ) + && version_compare( \PHPUnit\Runner\Version::id(), '8.0.0', '>=' ) ) + ) { + // This autoloader is only needed when the tests are being run on PHPUnit 7. + return false; + } + + $relative_path = self::$supported_classes[ $class_name ]; + $file = \realpath( __DIR__ . $relative_path ); + + if ( false === $file || @\file_exists( $file ) === false ) { + return false; + } + + require_once $file; + return true; + } +}