diff --git a/composer.json b/composer.json
index 71dcc9605c..24e405d9bd 100644
--- a/composer.json
+++ b/composer.json
@@ -50,10 +50,12 @@
     "scripts": {
         "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
         "post-autoload-dump": [
-          "Drupal\\Core\\Composer\\Composer::ensureHtaccess"
+          "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
+          "Drupal\\Core\\Composer\\Composer::upgradePHPUnit"
         ],
         "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
         "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
+        "drupal-phpunit-upgrade": "@composer upgrade phpunit/phpunit --with-dependencies",
         "phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
         "phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
     },
diff --git a/core/composer.json b/core/composer.json
index 31bc51a0fa..c4bb384b92 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -44,7 +44,7 @@
         "jcalderonzumba/gastonjs": "^1.0.2",
         "jcalderonzumba/mink-phantomjs-driver": "^0.3.1",
         "mikey179/vfsStream": "^1.2",
-        "phpunit/phpunit": ">=4.8.35 <5",
+        "phpunit/phpunit": "^4.8.35 || ^6.1",
         "phpspec/prophecy": "^1.4",
         "symfony/css-selector": "~3.2.8",
         "symfony/phpunit-bridge": "^3.4.0@beta"
diff --git a/core/lib/Drupal/Core/Composer/Composer.php b/core/lib/Drupal/Core/Composer/Composer.php
index 016f93a348..8bfc7bb8c2 100644
--- a/core/lib/Drupal/Core/Composer/Composer.php
+++ b/core/lib/Drupal/Core/Composer/Composer.php
@@ -6,6 +6,7 @@
 use Composer\Script\Event;
 use Composer\Installer\PackageEvent;
 use Composer\Semver\Constraint\Constraint;
+use PHPUnit\Runner\Version;
 
 /**
  * Provides static functions for composer script events.
@@ -143,6 +144,24 @@ public static function ensureHtaccess(Event $event) {
     }
   }
 
+  /**
+   * Fires the drupal-phpunit-upgrade script event if necessary.
+   *
+   * @param \Composer\Script\Event $event
+   */
+  public static function upgradePHPUnit(Event $event) {
+    if (class_exists('PHPUnit_Runner_Version')) {
+      $phpunit_version = \PHPUnit_Runner_Version::id();
+    }
+    if (class_exists('\PHPUnit\Runner\Version')) {
+      $phpunit_version = Version::id();
+    }
+    // @todo if we haven't determine version throw an error.
+    if (version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, '7.1') >= 0 && version_compare($phpunit_version, '6.0') < 0) {
+      $event->getComposer()->getEventDispatcher()->dispatchScript('drupal-phpunit-upgrade');
+    }
+  }
+
   /**
    * Remove possibly problematic test files from vendored projects.
    *
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 4b6f421e55..441b2398f4 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -18,7 +18,7 @@
 use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 use Drupal\Tests\EntityViewTrait;
 use Drupal\Tests\block\Traits\BlockCreationTrait as BaseBlockCreationTrait;
-use Drupal\Tests\Listeners\DeprecationListener;
+use Drupal\Tests\Listeners\DeprecationListenerTrait;
 use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
 use Drupal\Tests\node\Traits\NodeCreationTrait;
 use Drupal\Tests\Traits\Core\CronRunTrait;
@@ -698,7 +698,7 @@ protected function curlHeaderCallback($curlHandler, $header) {
       if ($parameters[1] === 'User deprecated function') {
         if (getenv('SYMFONY_DEPRECATIONS_HELPER') !== 'disabled') {
           $message = (string) $parameters[0];
-          if (!in_array($message, DeprecationListener::getSkippedDeprecations())) {
+          if (!in_array($message, DeprecationListenerTrait::getSkippedDeprecations())) {
             call_user_func_array([&$this, 'error'], $parameters);
           }
         }
diff --git a/core/modules/tour/src/Tests/TourTestBase.php b/core/modules/tour/src/Tests/TourTestBase.php
index e139650706..f551c8151b 100644
--- a/core/modules/tour/src/Tests/TourTestBase.php
+++ b/core/modules/tour/src/Tests/TourTestBase.php
@@ -14,6 +14,17 @@
  */
 abstract class TourTestBase extends WebTestBase {
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    // Support both PHPUnit 4 and 6.
+    if (!class_exists('\PHPUnit_Util_XML') && class_exists('\PHPUnit\Util\XML')) {
+      class_alias('\PHPUnit\Util\XML', '\PHPUnit_Util_XML');
+    }
+    parent::setUp();
+  }
+
   /**
    * Assert function to determine if tips rendered to the page
    * have a corresponding page element.
diff --git a/core/modules/update/tests/src/Unit/UpdateFetcherTest.php b/core/modules/update/tests/src/Unit/UpdateFetcherTest.php
index c3e447d1fc..61c767deda 100644
--- a/core/modules/update/tests/src/Unit/UpdateFetcherTest.php
+++ b/core/modules/update/tests/src/Unit/UpdateFetcherTest.php
@@ -28,7 +28,7 @@ class UpdateFetcherTest extends UnitTestCase {
    */
   protected function setUp() {
     $config_factory = $this->getConfigFactoryStub(['update.settings' => ['fetch_url' => 'http://www.example.com']]);
-    $http_client_mock = $this->getMock('\GuzzleHttp\ClientInterface');
+    $http_client_mock = $this->createMock('\GuzzleHttp\ClientInterface');
     $this->updateFetcher = new UpdateFetcher($config_factory, $http_client_mock);
   }
 
diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index bfe74673b2..750c6e2b50 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -49,16 +49,11 @@
     </testsuite>
   </testsuites>
   <listeners>
-    <listener class="\Drupal\Tests\Listeners\DeprecationListener">
+    <listener class="\Drupal\Tests\Listeners\DrupalListener">
     </listener>
-    <!-- The Symfony deprecation listener has to come after the Drupal
-    deprecation listener -->
+    <!-- The Symfony deprecation listener has to come after the Drupal listener -->
     <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
     </listener>
-    <listener class="\Drupal\Tests\Listeners\DrupalStandardsListener">
-    </listener>
-    <listener class="\Drupal\Tests\Listeners\DrupalComponentTestListener">
-    </listener>
   </listeners>
   <!-- Filter for coverage reports. -->
   <filter>
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index 32c97b63b5..91da81edf8 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -20,6 +20,7 @@
 use Drupal\simpletest\AssertContentTrait;
 use Drupal\Tests\AssertHelperTrait;
 use Drupal\Tests\ConfigTestTrait;
+use Drupal\Tests\Phpunit5FCTrait;
 use Drupal\Tests\RandomGeneratorTrait;
 use Drupal\Tests\TestRequirementsTrait;
 use Drupal\simpletest\TestServiceProvider;
@@ -76,6 +77,7 @@
   use RandomGeneratorTrait;
   use ConfigTestTrait;
   use TestRequirementsTrait;
+  use Phpunit5FCTrait;
 
   /**
    * {@inheritdoc}
diff --git a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php
index 1a649ae510..dbbb6ec081 100644
--- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php
+++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\Component\Diff\Engine\DiffOp;
 use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Error\Error;
 
 /**
  * Test DiffOp base class.
@@ -24,7 +25,12 @@ class DiffOpTest extends TestCase {
    * @covers ::reverse
    */
   public function testReverse() {
-    $this->setExpectedException(\PHPUnit_Framework_Error::class);
+    if (method_exists($this, 'expectException')) {
+      $this->expectException(Error::class);
+    }
+    else {
+      $this->setExpectedException(\PHPUnit_Framework_Error::class);
+    }
     $op = new DiffOp();
     $result = $op->reverse();
   }
diff --git a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php
index 52e1b83c03..168d1603e3 100644
--- a/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php
+++ b/core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php
@@ -5,7 +5,7 @@
 use Drupal\Component\PhpStorage\FileStorage;
 use Drupal\Component\Utility\Random;
 use org\bovigo\vfs\vfsStreamDirectory;
-use PHPUnit_Framework_Error_Warning;
+use PHPUnit\Framework\Error\Warning;
 
 /**
  * @coversDefaultClass \Drupal\Component\PhpStorage\FileStorage
@@ -99,7 +99,13 @@ public function testCreateDirectoryFailWarning() {
       'bin' => 'test',
     ]);
     $code = "<?php\n echo 'here';";
-    $this->setExpectedException(PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied');
+    if (method_exists($this, 'expectException')) {
+      $this->expectException(Warning::class);
+      $this->expectExceptionMessage('mkdir(): Permission Denied');
+    }
+    else {
+      $this->setExpectedException(\PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied');
+    }
     $storage->save('subdirectory/foo.php', $code);
   }
 
diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListener.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
similarity index 97%
rename from core/tests/Drupal/Tests/Listeners/DeprecationListener.php
rename to core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
index 80b3d31c97..8b828e0178 100644
--- a/core/tests/Drupal/Tests/Listeners/DeprecationListener.php
+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -9,12 +9,18 @@
  *   This class will be removed once all the deprecation notices have been
  *   fixed.
  */
-class DeprecationListener extends \PHPUnit_Framework_BaseTestListener {
+trait DeprecationListenerTrait {
 
   /**
-   * {@inheritdoc}
+   * Reacts to the end of a test.
+   *
+   * @param $test
+   *   The test object that has ended its test run.
+   * @param float $time
+   *   The time the test took.
    */
-  public function endTest(\PHPUnit_Framework_Test $test, $time) {
+  protected function deprecationEndTest($test, $time) {
+    /** @var \PHPUnit\Framework\Test $test */
     // Need to edit the file of deprecations.
     if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) {
       $deprecations = file_get_contents($file);
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
similarity index 52%
rename from core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php
rename to core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
index c349677305..0284f6da90 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListener.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalComponentTestListenerTrait.php
@@ -5,20 +5,28 @@
 use Drupal\KernelTests\KernelTestBase;;
 use Drupal\Tests\BrowserTestBase;;
 use Drupal\Tests\UnitTestCase;
-use PHPUnit\Framework\BaseTestListener;
+use PHPUnit\Framework\AssertionFailedError;
 
 /**
  * Ensures that no component tests are extending a core test base class.
+ *
+ * @internal
  */
-class DrupalComponentTestListener extends BaseTestListener {
+trait DrupalComponentTestListenerTrait {
 
   /**
-   * {@inheritdoc}
+   * Reacts to the end of a test.
+   *
+   * @param $test
+   *   The test object that has ended its test run.
+   * @param float $time
+   *   The time the test took.
    */
-  public function endTest(\PHPUnit_Framework_Test $test, $time) {
+  protected function componentEndTest($test, $time) {
+    /** @var \PHPUnit\Framework\Test $test */
     if (substr($test->toString(), 0, 22) == 'Drupal\Tests\Component') {
       if ($test instanceof BrowserTestBase || $test instanceof KernelTestBase || $test instanceof UnitTestCase) {
-        $error = new \PHPUnit_Framework_AssertionFailedError('Component tests should not extend a core test base class.');
+        $error = new AssertionFailedError('Component tests should not extend a core test base class.');
         $test->getTestResultObject()->addFailure($test, $error, $time);
       }
     }
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/DrupalListener.php
new file mode 100644
index 0000000000..db0c822588
--- /dev/null
+++ b/core/tests/Drupal/Tests/Listeners/DrupalListener.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Drupal\Tests\Listeners;
+
+use PHPUnit\Framework\BaseTestListener;
+use PHPUnit\Framework\Test;
+
+if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) {
+  class_alias('Drupal\Tests\Listeners\Legacy\DrupalListener', 'Drupal\Tests\Listeners\DrupalListener');
+  // Using an early return instead of a else does not work when using the
+  // PHPUnit phar due to some weird PHP behavior (the class gets defined without
+  // executing the code before it and so the definition is not properly
+  // conditional).
+}
+else {
+  /**
+   * Removes deprecations that we are yet to fix.
+   *
+   * @internal
+   */
+  class DrupalListener extends BaseTestListener {
+    use DeprecationListenerTrait;
+    use DrupalComponentTestListenerTrait;
+    use DrupalStandardsListenerTrait;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function endTest(Test $test, $time) {
+      $this->deprecationEndTest($test, $time);
+      $this->componentEndTest($test, $time);
+      $this->standardsEndTest($test, $time);
+    }
+
+  }
+}
diff --git a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
similarity index 80%
rename from core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php
rename to core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
index fd15f8218b..d94299cc9f 100644
--- a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php
+++ b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php
@@ -2,15 +2,18 @@
 
 namespace Drupal\Tests\Listeners;
 
-use PHPUnit\Framework\BaseTestListener;
+use PHPUnit\Framework\AssertionFailedError;
 use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
 
 /**
  * Listens for PHPUnit tests and fails those with invalid coverage annotations.
  *
  * Enforces various coding standards within test runs.
+ *
+ * @internal
  */
-class DrupalStandardsListener extends BaseTestListener {
+trait DrupalStandardsListenerTrait {
 
   /**
    * Signals a coding standards failure to the user.
@@ -21,10 +24,10 @@ class DrupalStandardsListener extends BaseTestListener {
    *   The message to add to the failure notice. The test class name and test
    *   name will be appended to this message automatically.
    */
-  protected function fail(TestCase $test, $message) {
+  private function fail(TestCase $test, $message) {
     // Add the report to the test's results.
     $message .= ': ' . get_class($test) . '::' . $test->getName();
-    $fail = new \PHPUnit_Framework_AssertionFailedError($message);
+    $fail = new AssertionFailedError($message);
     $result = $test->getTestResultObject();
     $result->addFailure($test, $fail, 0);
   }
@@ -38,7 +41,7 @@ protected function fail(TestCase $test, $message) {
    * @return bool
    *   TRUE if the class exists, FALSE otherwise.
    */
-  protected function classExists($class) {
+  private function classExists($class) {
     return class_exists($class, TRUE) || trait_exists($class, TRUE) || interface_exists($class, TRUE);
   }
 
@@ -50,7 +53,7 @@ protected function classExists($class) {
    * @param \PHPUnit\Framework\TestCase $test
    *   The test to examine.
    */
-  public function checkValidCoversForTest(TestCase $test) {
+  private function checkValidCoversForTest(TestCase $test) {
     // If we're generating a coverage report already, don't do anything here.
     if ($test->getTestResultObject() && $test->getTestResultObject()->getCollectCodeCoverageInformation()) {
       return;
@@ -141,7 +144,7 @@ public function checkValidCoversForTest(TestCase $test) {
   }
 
   /**
-   * {@inheritdoc}
+   * Reacts to the end of a test.
    *
    * We must mark this method as belonging to the special legacy group because
    * it might trigger an E_USER_DEPRECATED error during coverage annotation
@@ -151,22 +154,58 @@ public function checkValidCoversForTest(TestCase $test) {
    *
    * @group legacy
    *
+   * @param $test
+   *   The test object that has ended its test run.
+   * @param float $time
+   *   The time the test took.
+   *
    * @see http://symfony.com/doc/current/components/phpunit_bridge.html#mark-tests-as-legacy
    */
-  public function endTest(\PHPUnit_Framework_Test $test, $time) {
+  private function doEndTest($test, $time) {
     // \PHPUnit_Framework_Test does not have any useful methods of its own for
     // our purpose, so we have to distinguish between the different known
     // subclasses.
     if ($test instanceof TestCase) {
       $this->checkValidCoversForTest($test);
     }
-    elseif ($test instanceof \PHPUnit_Framework_TestSuite) {
+    elseif ($this->isTestSuite($test)) {
       foreach ($test->getGroupDetails() as $tests) {
         foreach ($tests as $test) {
-          $this->endTest($test, $time);
+          $this->doEndTest($test, $time);
         }
       }
     }
   }
 
+  /**
+   * Determine if a test object is a test suite regardless of PHPUnit version.
+   *
+   * @param $test
+   *   The test object to test if it is a test suite.
+   *
+   * @return bool
+   *   TRUE if it is a test suite, FALSE if not.
+   */
+  private function isTestSuite($test) {
+    if (class_exists('\PHPUnit_Framework_TestSuite') && $test instanceof \PHPUnit_Framework_TestSuite) {
+      return TRUE;
+    }
+    if (class_exists('PHPUnit\Framework\TestSuite') && $test instanceof TestSuite) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Reacts to the end of a test.
+   *
+   * @param $test
+   *   The test object that has ended its test run.
+   * @param float $time
+   *   The time the test took.
+   */
+  protected function standardsEndTest($test, $time) {
+    $this->doEndTest($test, $time);
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php
new file mode 100644
index 0000000000..f7c2c76668
--- /dev/null
+++ b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\Tests\Listeners\Legacy;
+
+use Drupal\Tests\Listeners\DeprecationListenerTrait;
+use Drupal\Tests\Listeners\DrupalComponentTestListenerTrait;
+use Drupal\Tests\Listeners\DrupalStandardsListenerTrait;
+
+/**
+ * Listens to PHPUnit test runs.
+ *
+ * @internal
+ *   This class is not public Drupal API.
+ */
+class DrupalListener extends \PHPUnit_Framework_BaseTestListener {
+  use DeprecationListenerTrait;
+  use DrupalComponentTestListenerTrait;
+  use DrupalStandardsListenerTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function endTest(\PHPUnit_Framework_Test $test, $time) {
+    $this->deprecationEndTest($test, $time);
+    $this->componentEndTest($test, $time);
+    $this->standardsEndTest($test, $time);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Phpunit5FCTrait.php b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
new file mode 100644
index 0000000000..d539f4333d
--- /dev/null
+++ b/core/tests/Drupal/Tests/Phpunit5FCTrait.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Drupal\Tests;
+
+/**
+ * This trait makes tests forward compatible with PHPUnit 5 and above.
+ */
+trait Phpunit5FCTrait {
+
+  /**
+   * Returns a mock object for the specified class using the available method.
+   *
+   * The getMock method is deprecated in PHPUnit 5 but the createMock method is
+   * not available in PHPUnit 4. To provide backward compatibility this trait
+   * provides the getMock method and uses createMock if this method is
+   * available on the parent class.
+   *
+   * @param string $originalClassName
+   *   Name of the class to mock.
+   * @param array|null $methods
+   *   When provided, only methods whose names are in the array are replaced
+   *   with a configurable test double. The behavior of the other methods is not
+   *   changed. Providing null means that no methods will be replaced.
+   * @param array $arguments
+   *   Parameters to pass to the original class' constructor.
+   * @param string $mockClassName
+   *   Class name for the generated test double class.
+   * @param bool $callOriginalConstructor
+   *   Can be used to disable the call to the original class' constructor.
+   * @param bool $callOriginalClone
+   *   Can be used to disable the call to the original class' clone constructor.
+   * @param bool $callAutoload
+   *   Can be used to disable __autoload() during the generation of the test
+   *   double class.
+   * @param bool $cloneArguments
+   * @param bool $callOriginalMethods
+   * @param object $proxyTarget
+   *
+   * @see \PHPUnit_Framework_TestCase::getMock
+   * @see https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-5.4.0
+   *
+   * @return \PHPUnit_Framework_MockObject_MockObject
+   *
+   * @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0.
+   *   Use \Drupal\Tests\Phpunit5FCTrait::createMock() instead.
+   *
+   * @see https://www.drupal.org/node/2907725
+   */
+  public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) {
+    return $this->createMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
+  }
+
+  /**
+   * Returns a mock object for the specified class using the available method.
+   *
+   * The getMock method is deprecated in PHPUnit 5 but the createMock method is
+   * not available in PHPUnit 4. To provide forward compatibility this trait
+   * provides the createMock method and uses createMock if this method is
+   * available on the parent class or falls back to getMock if it isn't.
+   *
+   * @param string $originalClassName
+   *   Name of the class to mock.
+   * @param array|null $methods
+   *   When provided, only methods whose names are in the array are replaced
+   *   with a configurable test double. The behavior of the other methods is not
+   *   changed. Providing null means that no methods will be replaced.
+   * @param array $arguments
+   *   Parameters to pass to the original class' constructor.
+   * @param string $mockClassName
+   *   Class name for the generated test double class.
+   * @param bool $callOriginalConstructor
+   *   Can be used to disable the call to the original class' constructor.
+   * @param bool $callOriginalClone
+   *   Can be used to disable the call to the original class' clone constructor.
+   * @param bool $callAutoload
+   *   Can be used to disable __autoload() during the generation of the test
+   *   double class.
+   * @param bool $cloneArguments
+   * @param bool $callOriginalMethods
+   * @param object $proxyTarget
+   *
+   * @see \PHPUnit_Framework_TestCase::getMock
+   *
+   * @return \PHPUnit_Framework_MockObject_MockObject
+   */
+  public function createMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) {
+    if ($this->isPhpunit5()) {
+      return parent::createMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
+    }
+    return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
+  }
+
+  /**
+   * Checks if the trait is used in a class extending the PHPUnit 5 TestCase.
+   *
+   * @return bool
+   */
+  private function isPhpunit5() {
+    // Get the parent class of the currently running test class.
+    $parent = get_parent_class($this);
+    // Ensure that the method_exists() check on PHPUnit 5's createMock method is
+    // carried out on the first parent of $this that does not have access to
+    // this trait's methods. This is because the trait also has a method called
+    // createMock(). Most often the check will be made on
+    // \PHPUnit\Framework\TestCase.
+    while (method_exists($parent, 'isPhpunit5')) {
+      $parent = get_parent_class($parent);
+    }
+    return method_exists($parent, 'createMock');
+  }
+
+  /**
+   * @todo
+   *
+   * @param $class
+   * @param null $message
+   */
+  public function setExpectedException($class, $message = NULL) {
+    if (method_exists($this, 'expectException')) {
+      $this->expectException($class);
+      if ($message !== NULL) {
+        $this->expectExceptionMessage($message);
+      }
+    }
+    else {
+      parent::setExpectedException($class, $message);
+    }
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php b/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php
new file mode 100644
index 0000000000..621003f6b3
--- /dev/null
+++ b/core/tests/Drupal/Tests/Phpunit5FCTraitTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Drupal\Tests;
+
+/**
+ * Test the PHPUnit 5 forward compatibility trait.
+ *
+ * @coversDefaultClass \Drupal\Tests\Phpunit5FCTrait
+ * @group simpletest
+ * @group Tests
+ */
+class Phpunit5FCTraitTest extends UnitTestCase {
+
+  /**
+   * Test that getMock is available and calls the correct parent method.
+   *
+   * @covers ::getMock
+   * @dataProvider providerMockVersions
+   */
+  public function testGetMock($className, $expected) {
+    $class = new $className();
+    $this->assertSame($expected, $class->getMock($this->randomMachineName()));
+  }
+
+  /**
+   * Test that createMock is available and calls the correct parent method.
+   *
+   * @covers ::createMock
+   * @dataProvider providerMockVersions
+   */
+  public function testCreateMock($className, $expected) {
+    $class = new $className();
+    $this->assertSame($expected, $class->createMock($this->randomMachineName()));
+  }
+
+  /**
+   * Return the class names and the string they return.
+   *
+   * @return array
+   */
+  public function providerMockVersions() {
+    return [
+      [UnitTestCasePhpunit4TestClass::class, 'PHPUnit 4'],
+      [UnitTestCasePhpunit4TestClassExtends::class, 'PHPUnit 4'],
+      [UnitTestCasePhpunit5TestClass::class, 'PHPUnit 5'],
+      [UnitTestCasePhpunit5TestClassExtends::class, 'PHPUnit 5'],
+    ];
+  }
+
+}
+
+/**
+ * Test class for \PHPUnit\Framework\TestCase in PHPUnit 4.
+ */
+class Phpunit4TestClass {
+  public function getMock($originalClassName) {
+    return 'PHPUnit 4';
+  }
+
+}
+
+/**
+ * Test class for \PHPUnit\Framework\TestCase in PHPUnit 5.
+ */
+class Phpunit5TestClass {
+  public function createMock($originalClassName) {
+    return 'PHPUnit 5';
+  }
+
+}
+
+/**
+ * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
+ */
+class UnitTestCasePhpunit4TestClass extends Phpunit4TestClass {
+  use Phpunit5FCTrait;
+
+}
+
+/**
+ * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
+ */
+class UnitTestCasePhpunit4TestClassExtends extends UnitTestCasePhpunit4TestClass {
+}
+
+/**
+ * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5.
+ */
+class UnitTestCasePhpunit5TestClass extends Phpunit5TestClass {
+  use Phpunit5FCTrait;
+
+}
+
+/**
+ * Test class for \Drupal\Tests\UnitTestCase with PHPUnit 5.
+ */
+class UnitTestCasePhpunit5TestClassExtends extends UnitTestCasePhpunit5TestClass {
+}
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 24ad6801bf..b4ac0c3805 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -17,6 +17,8 @@
  */
 abstract class UnitTestCase extends TestCase {
 
+  use Phpunit5FCTrait;
+
   /**
    * The random generator.
    *
@@ -135,7 +137,7 @@ public function getConfigFactoryStub(array $configs = []) {
     }
     // Construct a config factory with the array of configuration object stubs
     // as its return map.
-    $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
+    $config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
     $config_factory->expects($this->any())
       ->method('get')
       ->will($this->returnValueMap($config_get_map));
@@ -157,7 +159,7 @@ public function getConfigFactoryStub(array $configs = []) {
    *   A mocked config storage.
    */
   public function getConfigStorageStub(array $configs) {
-    $config_storage = $this->getMock('Drupal\Core\Config\NullStorage');
+    $config_storage = $this->createMock('Drupal\Core\Config\NullStorage');
     $config_storage->expects($this->any())
       ->method('listAll')
       ->will($this->returnValue(array_keys($configs)));
@@ -211,7 +213,7 @@ protected function getBlockMockWithMachineName($machine_name) {
    *   A mock translation object.
    */
   public function getStringTranslationStub() {
-    $translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
+    $translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
     $translation->expects($this->any())
       ->method('translate')
       ->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) {
@@ -241,7 +243,7 @@ public function getStringTranslationStub() {
    *   The container with the cache tags invalidator service.
    */
   protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
-    $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+    $container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
     $container->expects($this->any())
       ->method('get')
       ->with('cache_tags.invalidator')
@@ -258,7 +260,7 @@ protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInte
    *   The class resolver stub.
    */
   protected function getClassResolverStub() {
-    $class_resolver = $this->getMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
+    $class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
     $class_resolver->expects($this->any())
       ->method('getInstanceFromDefinition')
       ->will($this->returnCallback(function ($class) {
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index f78b69ff04..f2edbd2d97 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -166,3 +166,38 @@ function drupal_phpunit_populate_class_loader() {
 // make PHP 5 and 7 handle assertion failures the same way, but this call does
 // not turn runtime assertions on if they weren't on already.
 Handle::register();
+
+// @todo Decide if we need put in some code for WebTestBase too since there are
+//   tests using PHPUnit_Util_XML for example.
+// PHPUnit 4 to PHPUnit 6 bridge. Tests written for PHPUnit 4 need to work on
+// PHPUnit 6 with a minimum of fuss.
+if (!class_exists('\PHPUnit_Framework_AssertionFailedError') && class_exists('\PHPUnit\Framework\AssertionFailedError')) {
+  class_alias('\PHPUnit\Framework\AssertionFailedError', '\PHPUnit_Framework_AssertionFailedError');
+}
+if (!class_exists('\PHPUnit_Framework_Error_Warning') && class_exists('\PHPUnit\Framework\Error\Warning')) {
+  class_alias('\PHPUnit\Framework\Error\Warning', '\PHPUnit_Framework_Error_Warning');
+}
+if (!class_exists('\PHPUnit_Framework_Error') && class_exists('\PHPUnit\Framework\Error\Error')) {
+  class_alias('\PHPUnit\Framework\Error\Error', '\PHPUnit_Framework_Error');
+}
+if (!class_exists('\PHPUnit_Util_Test') && class_exists('\PHPUnit\Util\Test')) {
+  class_alias('\PHPUnit\Util\Test', '\PHPUnit_Util_Test');
+}
+if (!class_exists('\PHPUnit_Util_XML') && class_exists('\PHPUnit\Util\XML')) {
+  class_alias('\PHPUnit\Util\XML', '\PHPUnit_Util_XML');
+}
+if (!class_exists('\PHPUnit_Framework_SkippedTestError') && class_exists('\PHPUnit\Framework\SkippedTestError')) {
+  class_alias('\PHPUnit\Framework\SkippedTestError', '\PHPUnit_Framework_SkippedTestError');
+}
+if (!class_exists('\PHPUnit_Framework_Exception') && class_exists('\PHPUnit\Framework\Exception')) {
+  class_alias('\PHPUnit\Framework\Exception', '\PHPUnit_Framework_Exception');
+}
+if (!class_exists('\PHPUnit_Framework_ExpectationFailedException') && class_exists('\PHPUnit\Framework\ExpectationFailedException')) {
+  class_alias('\PHPUnit\Framework\ExpectationFailedException', '\PHPUnit_Framework_ExpectationFailedException');
+}
+if (!class_exists('\PHPUnit_Framework_Constraint_Count') && class_exists('\PHPUnit\Framework\Constraint\Count')) {
+  class_alias('\PHPUnit\Framework\Constraint\Count', '\PHPUnit_Framework_Constraint_Count');
+}
+if (!class_exists('\PHPUnit_Framework_MockObject_Matcher_InvokedRecorder') && class_exists('\PHPUnit\Framework\MockObject\Matcher\InvokedRecorder')) {
+  class_alias('\PHPUnit\Framework\MockObject\Matcher\InvokedRecorder', '\PHPUnit_Framework_MockObject_Matcher_InvokedRecorder');
+}
