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
This commit is contained in:
Sergey Biryukov 2021-08-04 19:24:14 +00:00
parent 0e442c4615
commit 461f7764e4
3 changed files with 67 additions and 14 deletions

View File

@ -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",

View File

@ -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(

View File

@ -0,0 +1,63 @@
<?php
/**
* Custom autoloader for the PHPUnit 9.x MockObject classes.
*
* Hack around PHPUnit < 9.3 mocking not being compatible with PHP 8.
*
* This is a temporary solution until the PHPUnit version constraints are widened.
*
* @since 5.9.0
*/
final class MockObject_Autoload {
/**
* A list of the classes this autoloader handles.
*
* @var string[] => 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;
}
}