From 5d457e37c5e716551c592c67a70c5cc7bbe2e20a Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Fri, 14 Feb 2020 12:21:47 +0000
Subject: [PATCH] Issue #3063887 by mondrake, alexpott, longwave, catch, xjm:
 Support PHPUnit 8 in Drupal 9, drop support for PHPUnit 7

---
 composer.json                                 |   2 +-
 composer.lock                                 | 142 ++++++++++++------
 .../Metapackage/DevDependencies/composer.json |   2 +-
 .../PinnedDevDependencies/composer.json       |   7 +-
 .../Database/Driver/sqlite/Connection.php     |   2 +-
 core/lib/Drupal/Core/Test/TestDiscovery.php   |   5 +
 core/phpunit.xml.dist                         |   3 +-
 core/scripts/run-tests.sh                     |   2 +
 .../PhpUnit8/ClassWriter.php                  |  54 +++++++
 .../Core/Entity/ContentEntityBaseUnitTest.php |   2 +-
 .../Tests/Core/Entity/EntityUnitTest.php      |   2 +-
 .../DefaultSingleLazyPluginCollectionTest.php |   4 +-
 .../Plugin/LazyPluginCollectionTestBase.php   |   6 +-
 .../Drupal/Tests/ExpectDeprecationTest.php    |  10 +-
 .../Listeners/DeprecationListenerTrait.php    |   9 ++
 .../Tests/Traits/ExpectDeprecationTrait.php   |   2 +-
 core/tests/bootstrap.php                      |   5 +-
 17 files changed, 191 insertions(+), 68 deletions(-)
 create mode 100644 core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/ClassWriter.php

diff --git a/composer.json b/composer.json
index 7cee81b8f9d8..9b0a881f216e 100644
--- a/composer.json
+++ b/composer.json
@@ -22,7 +22,7 @@
         "composer/composer": "^1.9.1",
         "drupal/coder": "^8.3.7",
         "mikey179/vfsstream": "^1.6.8",
-        "phpunit/phpunit": "^7",
+        "phpunit/phpunit": "^8.4.1",
         "phpspec/prophecy": "^1.7",
         "symfony/css-selector": "^4.4",
         "symfony/phpunit-bridge": "^4.4",
diff --git a/composer.lock b/composer.lock
index 78c426b6b48b..ea7db60e206a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "851ca5677985628c73d2d91f044760ce",
+    "content-hash": "d8477fb085432c15724c090b7d20f6d2",
     "packages": [
         {
             "name": "asm89/stack-cors",
@@ -4985,40 +4985,40 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "6.1.4",
+            "version": "7.0.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
+                "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
-                "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf",
+                "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf",
                 "shasum": ""
             },
             "require": {
                 "ext-dom": "*",
                 "ext-xmlwriter": "*",
-                "php": "^7.1",
-                "phpunit/php-file-iterator": "^2.0",
+                "php": "^7.2",
+                "phpunit/php-file-iterator": "^2.0.2",
                 "phpunit/php-text-template": "^1.2.1",
-                "phpunit/php-token-stream": "^3.0",
+                "phpunit/php-token-stream": "^3.1.1",
                 "sebastian/code-unit-reverse-lookup": "^1.0.1",
-                "sebastian/environment": "^3.1 || ^4.0",
+                "sebastian/environment": "^4.2.2",
                 "sebastian/version": "^2.0.1",
-                "theseer/tokenizer": "^1.1"
+                "theseer/tokenizer": "^1.1.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^7.0"
+                "phpunit/phpunit": "^8.2.2"
             },
             "suggest": {
-                "ext-xdebug": "^2.6.0"
+                "ext-xdebug": "^2.7.2"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "6.1-dev"
+                    "dev-master": "7.0-dev"
                 }
             },
             "autoload": {
@@ -5044,7 +5044,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2018-10-31T16:06:48+00:00"
+            "time": "2019-11-20T13:55:58+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -5237,53 +5237,52 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "7.5.20",
+            "version": "8.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "9467db479d1b0487c99733bb1e7944d32deded2c"
+                "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c",
-                "reference": "9467db479d1b0487c99733bb1e7944d32deded2c",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/018b6ac3c8ab20916db85fa91bf6465acb64d1e0",
+                "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0",
                 "shasum": ""
             },
             "require": {
-                "doctrine/instantiator": "^1.1",
+                "doctrine/instantiator": "^1.2.0",
                 "ext-dom": "*",
                 "ext-json": "*",
                 "ext-libxml": "*",
                 "ext-mbstring": "*",
                 "ext-xml": "*",
-                "myclabs/deep-copy": "^1.7",
-                "phar-io/manifest": "^1.0.2",
-                "phar-io/version": "^2.0",
-                "php": "^7.1",
-                "phpspec/prophecy": "^1.7",
-                "phpunit/php-code-coverage": "^6.0.7",
-                "phpunit/php-file-iterator": "^2.0.1",
+                "ext-xmlwriter": "*",
+                "myclabs/deep-copy": "^1.9.1",
+                "phar-io/manifest": "^1.0.3",
+                "phar-io/version": "^2.0.1",
+                "php": "^7.2",
+                "phpspec/prophecy": "^1.8.1",
+                "phpunit/php-code-coverage": "^7.0.7",
+                "phpunit/php-file-iterator": "^2.0.2",
                 "phpunit/php-text-template": "^1.2.1",
-                "phpunit/php-timer": "^2.1",
-                "sebastian/comparator": "^3.0",
-                "sebastian/diff": "^3.0",
-                "sebastian/environment": "^4.0",
-                "sebastian/exporter": "^3.1",
-                "sebastian/global-state": "^2.0",
+                "phpunit/php-timer": "^2.1.2",
+                "sebastian/comparator": "^3.0.2",
+                "sebastian/diff": "^3.0.2",
+                "sebastian/environment": "^4.2.2",
+                "sebastian/exporter": "^3.1.1",
+                "sebastian/global-state": "^3.0.0",
                 "sebastian/object-enumerator": "^3.0.3",
-                "sebastian/resource-operations": "^2.0",
+                "sebastian/resource-operations": "^2.0.1",
+                "sebastian/type": "^1.1.3",
                 "sebastian/version": "^2.0.1"
             },
-            "conflict": {
-                "phpunit/phpunit-mock-objects": "*"
-            },
             "require-dev": {
                 "ext-pdo": "*"
             },
             "suggest": {
                 "ext-soap": "*",
                 "ext-xdebug": "*",
-                "phpunit/php-invoker": "^2.0"
+                "phpunit/php-invoker": "^2.0.0"
             },
             "bin": [
                 "phpunit"
@@ -5291,7 +5290,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "7.5-dev"
+                    "dev-master": "8.5-dev"
                 }
             },
             "autoload": {
@@ -5317,7 +5316,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2020-01-08T08:45:45+00:00"
+            "time": "2020-01-08T08:49:49+00:00"
         },
         {
             "name": "sebastian/code-unit-reverse-lookup",
@@ -5606,23 +5605,26 @@
         },
         {
             "name": "sebastian/global-state",
-            "version": "2.0.0",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/global-state.git",
-                "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
-                "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.0"
+                "php": "^7.2",
+                "sebastian/object-reflector": "^1.1.1",
+                "sebastian/recursion-context": "^3.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^6.0"
+                "ext-dom": "*",
+                "phpunit/phpunit": "^8.0"
             },
             "suggest": {
                 "ext-uopz": "*"
@@ -5630,7 +5632,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.0-dev"
+                    "dev-master": "3.0-dev"
                 }
             },
             "autoload": {
@@ -5653,7 +5655,7 @@
             "keywords": [
                 "global state"
             ],
-            "time": "2017-04-27T15:39:26+00:00"
+            "time": "2019-02-01T05:30:01+00:00"
         },
         {
             "name": "sebastian/object-enumerator",
@@ -5842,6 +5844,52 @@
             "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
             "time": "2018-10-04T04:07:39+00:00"
         },
+        {
+            "name": "sebastian/type",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/type.git",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Collection of value objects that represent the types of the PHP type system",
+            "homepage": "https://github.com/sebastianbergmann/type",
+            "time": "2019-07-02T08:10:15+00:00"
+        },
         {
             "name": "sebastian/version",
             "version": "2.0.1",
diff --git a/composer/Metapackage/DevDependencies/composer.json b/composer/Metapackage/DevDependencies/composer.json
index 3f3dfbb4ad1b..6b8e783cc4dc 100644
--- a/composer/Metapackage/DevDependencies/composer.json
+++ b/composer/Metapackage/DevDependencies/composer.json
@@ -16,7 +16,7 @@
         "justinrainbow/json-schema": "^5.2",
         "mikey179/vfsstream": "^1.6.8",
         "phpspec/prophecy": "^1.7",
-        "phpunit/phpunit": "^7",
+        "phpunit/phpunit": "^8.4.1",
         "symfony/browser-kit": "^4.4",
         "symfony/css-selector": "^4.4",
         "symfony/debug": "^4.4",
diff --git a/composer/Metapackage/PinnedDevDependencies/composer.json b/composer/Metapackage/PinnedDevDependencies/composer.json
index 8eeed3b8806b..cc57ded7c690 100644
--- a/composer/Metapackage/PinnedDevDependencies/composer.json
+++ b/composer/Metapackage/PinnedDevDependencies/composer.json
@@ -30,22 +30,23 @@
         "phpdocumentor/reflection-docblock": "4.3.4",
         "phpdocumentor/type-resolver": "1.0.1",
         "phpspec/prophecy": "v1.10.2",
-        "phpunit/php-code-coverage": "6.1.4",
+        "phpunit/php-code-coverage": "7.0.10",
         "phpunit/php-file-iterator": "2.0.2",
         "phpunit/php-text-template": "1.2.1",
         "phpunit/php-timer": "2.1.2",
         "phpunit/php-token-stream": "3.1.1",
-        "phpunit/phpunit": "7.5.20",
+        "phpunit/phpunit": "8.5.2",
         "sebastian/code-unit-reverse-lookup": "1.0.1",
         "sebastian/comparator": "3.0.2",
         "sebastian/diff": "3.0.2",
         "sebastian/environment": "4.2.3",
         "sebastian/exporter": "3.1.2",
-        "sebastian/global-state": "2.0.0",
+        "sebastian/global-state": "3.0.0",
         "sebastian/object-enumerator": "3.0.3",
         "sebastian/object-reflector": "1.1.1",
         "sebastian/recursion-context": "3.0.0",
         "sebastian/resource-operations": "2.0.1",
+        "sebastian/type": "1.1.3",
         "sebastian/version": "2.0.1",
         "seld/jsonlint": "1.7.2",
         "seld/phar-utils": "1.0.2",
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
index fe007cfe0511..fa382d3f572b 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
@@ -180,7 +180,7 @@ public function __destruct() {
           $count = $this->query('SELECT COUNT(*) FROM ' . $prefix . '.sqlite_master WHERE type = :type AND name NOT LIKE :pattern', [':type' => 'table', ':pattern' => 'sqlite_%'])->fetchField();
 
           // We can prune the database file if it doesn't have any tables.
-          if ($count == 0) {
+          if ($count == 0 && file_exists($this->connectionOptions['database'] . '-' . $prefix)) {
             // Detaching the database fails at this point, but no other queries
             // are executed after the connection is destructed so we can simply
             // remove the database file.
diff --git a/core/lib/Drupal/Core/Test/TestDiscovery.php b/core/lib/Drupal/Core/Test/TestDiscovery.php
index 7c6242f950ae..a2fc30686e1f 100644
--- a/core/lib/Drupal/Core/Test/TestDiscovery.php
+++ b/core/lib/Drupal/Core/Test/TestDiscovery.php
@@ -7,6 +7,7 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Test\Exception\MissingGroupException;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit8\ClassWriter;
 use PHPUnit\Util\Test;
 
 /**
@@ -116,6 +117,10 @@ public function registerTestNamespaces() {
       $this->classLoader->addPsr4($prefix, $paths);
     }
 
+    $loader = require __DIR__ . '/../../../../../autoload.php';
+    // Ensure we have a valid TestCase class.
+    ClassWriter::mutateTestBase($loader);
+
     return $this->testNamespaces;
   }
 
diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index 01a359689387..bd9c8338097f 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -9,7 +9,8 @@
          beStrictAboutTestsThatDoNotTestAnything="true"
          beStrictAboutOutputDuringTests="true"
          beStrictAboutChangesToGlobalState="true"
-         printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter">
+         printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
+         cacheResult="false">
   <php>
     <!-- Set error reporting to E_ALL. -->
     <ini name="error_reporting" value="32767"/>
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index d155284ebdbf..61104aceef2f 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -18,6 +18,7 @@
 use Drupal\Core\Test\TestDatabase;
 use Drupal\Core\Test\TestRunnerKernel;
 use Drupal\Core\Test\TestDiscovery;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit8\ClassWriter;
 use PHPUnit\Framework\TestCase;
 use PHPUnit\Runner\Version;
 use Symfony\Component\Console\Output\ConsoleOutput;
@@ -504,6 +505,7 @@ function simpletest_script_init() {
   $autoloader = require_once __DIR__ . '/../../autoload.php';
   // The PHPUnit compatibility layer needs to be available to autoload tests.
   $autoloader->add('Drupal\\TestTools', __DIR__ . '/../tests');
+  ClassWriter::mutateTestBase($autoloader);
 
   // Get URL from arguments.
   if (!empty($args['url'])) {
diff --git a/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/ClassWriter.php b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/ClassWriter.php
new file mode 100644
index 000000000000..77ccb953390b
--- /dev/null
+++ b/core/tests/Drupal/TestTools/PhpUnitCompatibility/PhpUnit8/ClassWriter.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit8;
+
+/**
+ * Helper class to rewrite PHPUnit's TestCase class.
+ *
+ * This class contains static methods only and is not meant to be instantiated.
+ *
+ * @internal
+ *   This should only be called by test running code. Drupal 9 will provide best
+ *   effort to maintain this class for the Drupal 9 cycle. However if changes to
+ *   PHP or PHPUnit make this impossible then support will be removed.
+ */
+final class ClassWriter {
+
+  /**
+   * This class should not be instantiated.
+   */
+  private function __construct() {
+  }
+
+  /**
+   * Mutates the TestCase class from PHPUnit to make it compatible with Drupal.
+   *
+   * @param object $autoloader
+   *   The autoloader.
+   *
+   * @throws \ReflectionException
+   */
+  public static function mutateTestBase($autoloader) {
+    // If the class exists already there is nothing we can do. Hopefully this
+    // is happening because this has been called already. The call from
+    // \Drupal\Core\Test\TestDiscovery::registerTestNamespaces() necessitates
+    // this protection.
+    if (class_exists('PHPUnit\Framework\TestCase', FALSE)) {
+      return;
+    }
+    // Inspired by Symfony's simple-phpunit remove typehints from TestCase.
+    $reflector = new \ReflectionClass($autoloader);
+    $vendor_dir = dirname(dirname($reflector->getFileName()));
+    // Mutate TestCase code to make it compatible with Drupal 8 and 9 tests.
+    $alteredCode = file_get_contents($alteredFile = $vendor_dir . '/phpunit/phpunit/src/Framework/TestCase.php');
+    $alteredCode = preg_replace('/^    ((?:protected|public)(?: static)? function \w+\(\)): void/m', '    $1', $alteredCode);
+    $alteredCode = str_replace("__DIR__ . '/../Util/", "'$vendor_dir/phpunit/phpunit/src/Util/", $alteredCode);
+    $filename = __DIR__ . '/../../../../../../sites/simpletest/TestCase.php';
+    // Only write when necessary.
+    if (!file_exists($filename) || md5_file($filename) !== md5($alteredCode)) {
+      file_put_contents($filename, $alteredCode);
+    }
+    include $filename;
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
index 1ce29a119964..63d83117dc8b 100644
--- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
@@ -479,7 +479,7 @@ public function testAccess() {
    */
   public function testLabel() {
 
-    $this->expectDeprecation('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
+    $this->addExpectedDeprecationMessage('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
 
     // Make a mock with one method that we use as the entity's label callback.
     // We check that it is called, and that the entity's label is the callback's
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index 7933611bf2eb..eea49f675010 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -173,7 +173,7 @@ public function testBundle() {
    */
   public function testLabel() {
 
-    $this->expectDeprecation('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
+    $this->addExpectedDeprecationMessage('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
 
     // Make a mock with one method that we use as the entity's uri_callback. We
     // check that it is called, and that the entity's label is the callback's
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php
index 807c33ed74d1..4182e48e1879 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php
@@ -5,7 +5,7 @@
 use Drupal\Component\Plugin\ConfigurableInterface;
 use Drupal\Component\Plugin\PluginBase;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
-use PHPUnit\Framework\MockObject\Matcher\InvokedRecorder;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
 
 /**
  * @coversDefaultClass \Drupal\Core\Plugin\DefaultSingleLazyPluginCollection
@@ -16,7 +16,7 @@ class DefaultSingleLazyPluginCollectionTest extends LazyPluginCollectionTestBase
   /**
    * {@inheritdoc}
    */
-  protected function setupPluginCollection(InvokedRecorder $create_count = NULL) {
+  protected function setupPluginCollection(InvocationOrder $create_count = NULL) {
     $definitions = $this->getPluginDefinitions();
     $this->pluginInstances['apple'] = new ConfigurablePlugin(['id' => 'apple', 'key' => 'value'], 'apple', $definitions['apple']);
     $this->pluginInstances['banana'] = new ConfigurablePlugin(['id' => 'banana', 'key' => 'other_value'], 'banana', $definitions['banana']);
diff --git a/core/tests/Drupal/Tests/Core/Plugin/LazyPluginCollectionTestBase.php b/core/tests/Drupal/Tests/Core/Plugin/LazyPluginCollectionTestBase.php
index 13bff00e58f3..38c00cefee9c 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/LazyPluginCollectionTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/LazyPluginCollectionTestBase.php
@@ -4,7 +4,7 @@
 
 use Drupal\Core\Plugin\DefaultLazyPluginCollection;
 use Drupal\Tests\UnitTestCase;
-use PHPUnit\Framework\MockObject\Matcher\InvokedRecorder;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
 
 /**
  * Provides a base class for plugin collection tests.
@@ -54,12 +54,12 @@ protected function setUp() {
   /**
    * Sets up the default plugin collection.
    *
-   * @param \PHPUnit\Framework\MockObject\Matcher\InvokedRecorder|null $create_count
+   * @param \PHPUnit\Framework\MockObject\Rule\InvocationOrder|null $create_count
    *   (optional) The number of times that createInstance() is expected to be
    *   called. For example, $this->any(), $this->once(), $this->exactly(6).
    *   Defaults to $this->never().
    */
-  protected function setupPluginCollection(InvokedRecorder $create_count = NULL) {
+  protected function setupPluginCollection(InvocationOrder $create_count = NULL) {
     $this->pluginInstances = [];
     $map = [];
     foreach ($this->getPluginDefinitions() as $plugin_id => $definition) {
diff --git a/core/tests/Drupal/Tests/ExpectDeprecationTest.php b/core/tests/Drupal/Tests/ExpectDeprecationTest.php
index aefb6a0ad927..0a44fd55ce5d 100644
--- a/core/tests/Drupal/Tests/ExpectDeprecationTest.php
+++ b/core/tests/Drupal/Tests/ExpectDeprecationTest.php
@@ -14,21 +14,21 @@ class ExpectDeprecationTest extends UnitTestCase {
   use ExpectDeprecationTrait;
 
   /**
-   * @covers ::expectDeprecation
+   * @covers ::addExpectedDeprecationMessage
    */
   public function testExpectDeprecation() {
-    $this->expectDeprecation('Test deprecation');
+    $this->addExpectedDeprecationMessage('Test deprecation');
     @trigger_error('Test deprecation', E_USER_DEPRECATED);
   }
 
   /**
-   * @covers ::expectDeprecation
+   * @covers ::addExpectedDeprecationMessage
    * @runInSeparateProcess
    * @preserveGlobalState disabled
    */
   public function testExpectDeprecationInIsolation() {
-    $this->expectDeprecation('Test isolated deprecation');
-    $this->expectDeprecation('Test isolated deprecation2');
+    $this->addExpectedDeprecationMessage('Test isolated deprecation');
+    $this->addExpectedDeprecationMessage('Test isolated deprecation2');
     @trigger_error('Test isolated deprecation', E_USER_DEPRECATED);
     @trigger_error('Test isolated deprecation2', E_USER_DEPRECATED);
   }
diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
index e4ec6c965395..69672dd41d70 100644
--- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -185,6 +185,15 @@ public static function getSkippedDeprecations() {
       // testing using \Symfony\Component\ErrorHandler\DebugClassLoader.
       'The "Twig\Environment::getTemplateClass()" method is considered internal. It may change without further notice. You should not extend it from "Drupal\Core\Template\TwigEnvironment".',
       '"Symfony\Component\DomCrawler\Crawler::text()" will normalize whitespaces by default in Symfony 5.0, set the second "$normalizeWhitespace" argument to false to retrieve the non-normalized version of the text.',
+      // PHPUnit 8.
+      "The \"Drupal\Tests\Listeners\AfterSymfonyListener\" class implements \"PHPUnit\Framework\TestListener\" that is deprecated Use the `TestHook` interfaces instead.",
+      "The \"Drupal\Tests\Listeners\AfterSymfonyListener\" class uses \"PHPUnit\Framework\TestListenerDefaultImplementation\" that is deprecated The `TestListener` interface is deprecated.",
+      "The \"PHPUnit\TextUI\ResultPrinter\" class is considered internal This class is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not use it from \"Drupal\Tests\Listeners\HtmlOutputPrinter\".",
+      "The \"Drupal\Tests\Listeners\DrupalListener\" class implements \"PHPUnit\Framework\TestListener\" that is deprecated Use the `TestHook` interfaces instead.",
+      "The \"Drupal\Tests\Listeners\DrupalListener\" class uses \"PHPUnit\Framework\TestListenerDefaultImplementation\" that is deprecated The `TestListener` interface is deprecated.",
+      "The \"PHPUnit\Framework\TestSuite\" class is considered internal This class is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not use it from \"Drupal\Tests\TestSuites\TestSuiteBase\".",
+      "The \"PHPUnit\Framework\TestCase::__construct()\" method is considered internal This method is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not extend it from \"Drupal\Tests\BrowserTestBase\".",
+      "The \"PHPUnit\Framework\TestCase::__construct()\" method is considered internal This method is not covered by the backward compatibility promise for PHPUnit. It may change without further notice. You should not extend it from \"Drupal\FunctionalTests\Update\UpdatePathTestBase\".",
     ];
   }
 
diff --git a/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php b/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php
index 91452522093c..d39e32dd54d5 100644
--- a/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php
+++ b/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php
@@ -25,7 +25,7 @@ trait ExpectDeprecationTrait {
    * @param string $message
    *   The expected deprecation message.
    */
-  protected function expectDeprecation($message) {
+  protected function addExpectedDeprecationMessage($message) {
     $this->expectedDeprecations([$message]);
   }
 
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 520c9d783521..75f02749aa89 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -8,6 +8,7 @@
  */
 
 use Drupal\Component\Assertion\Handle;
+use Drupal\TestTools\PhpUnitCompatibility\PhpUnit8\ClassWriter;
 
 /**
  * Finds all valid extension directories recursively within a given directory.
@@ -150,7 +151,9 @@ function drupal_phpunit_populate_class_loader() {
 }
 
 // Do class loader population.
-drupal_phpunit_populate_class_loader();
+$loader = drupal_phpunit_populate_class_loader();
+
+ClassWriter::mutateTestBase($loader);
 
 // Set sane locale settings, to ensure consistent string, dates, times and
 // numbers handling.
-- 
GitLab