diff --git a/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryCachedTest.php b/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryCachedTest.php
new file mode 100644
index 0000000000..ef839c9075
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryCachedTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Component\FileCache\FileCacheFactory;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery
+ * @group Annotation
+ */
+class AnnotatedClassDiscoveryCachedTest extends TestCase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Ensure that FileCacheFactory has a prefix.
+    FileCacheFactory::setPrefix('prefix');
+  }
+
+  /**
+   * Test that getDefinitions() retrieves the file cache correctly.
+   *
+   * @covers ::getDefinitions
+   */
+  public function testGetDefinitions() {
+    // Path to the classes which we'll discover and parse annotation.
+    $discovery_path  = __DIR__ . '/Fixtures';
+    // File path that should be discovered within that directory.
+    $file_path = $discovery_path . '/PluginNamespace/DiscoveryTest1.php';
+
+    $discovery = new AnnotatedClassDiscovery(['com\example' => [$discovery_path]]);
+    $this->assertEquals([
+      'discovery_test_1' => [
+        'id' => 'discovery_test_1',
+        'class' => 'com\example\PluginNamespace\DiscoveryTest1',
+      ],
+    ], $discovery->getDefinitions());
+
+    // Gain access to the file cache so we can change it.
+    $ref_file_cache = new \ReflectionProperty($discovery, 'fileCache');
+    $ref_file_cache->setAccessible(TRUE);
+    /* @var $file_cache \Drupal\Component\FileCache\FileCacheInterface */
+    $file_cache = $ref_file_cache->getValue($discovery);
+    // The file cache is keyed by the file path, and we'll add some known
+    // content to test against.
+    $file_cache->set($file_path, [
+      'id' => 'wrong_id',
+      'content' => serialize(['an' => 'array']),
+    ]);
+
+    // Now perform the same query and check for the cached results.
+    $this->assertEquals([
+      'wrong_id' => [
+        'an' => 'array',
+      ],
+    ], $discovery->getDefinitions());
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryTest.php b/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryTest.php
new file mode 100644
index 0000000000..e2de5ca210
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/AnnotatedClassDiscoveryTest.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Component\FileCache\FileCacheFactory;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery
+ * @group Annotation
+ */
+class AnnotatedClassDiscoveryTest extends TestCase {
+
+  /**
+   * Original file cache configuration from before we disable it.
+   *
+   * @var array
+   */
+  protected $originalFileCacheConfig;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    // Ensure that the NullFileCache implementation is used for the FileCache as
+    // unit tests should not be relying on caches implicitly.
+    $this->originalFileCacheConfig = FileCacheFactory::getConfiguration();
+    FileCacheFactory::setConfiguration([FileCacheFactory::DISABLE_CACHE => TRUE]);
+    // Ensure that FileCacheFactory has a prefix.
+    FileCacheFactory::setPrefix('prefix');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    FileCacheFactory::setConfiguration($this->originalFileCacheConfig);
+    parent::tearDown();
+  }
+
+  /**
+   * @covers ::__construct
+   * @covers ::getPluginNamespaces
+   */
+  public function testGetPluginNamespaces() {
+    $discovery = new AnnotatedClassDiscovery(['com/example' => [__DIR__]]);
+
+    $reflection = new \ReflectionMethod($discovery, 'getPluginNamespaces');
+    $reflection->setAccessible(TRUE);
+
+    $result = $reflection->invoke($discovery);
+    $this->assertEquals(['com/example' => [__DIR__]], $result);
+  }
+
+  /**
+   * @covers ::getDefinitions
+   * @covers ::prepareAnnotationDefinition
+   * @covers ::getAnnotationReader
+   */
+  public function testGetDefinitions() {
+    $discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']]);
+    $this->assertEquals([
+      'discovery_test_1' => [
+        'id' => 'discovery_test_1',
+        'class' => 'com\example\PluginNamespace\DiscoveryTest1',
+      ],
+    ], $discovery->getDefinitions());
+
+    $custom_annotation_discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']], CustomPlugin::class, ['Drupal\Tests\Component\Annotation']);
+    $this->assertEquals([
+      'discovery_test_1' => [
+        'id' => 'discovery_test_1',
+        'class' => 'com\example\PluginNamespace\DiscoveryTest1',
+        'title' => 'Discovery test plugin',
+      ],
+    ], $custom_annotation_discovery->getDefinitions());
+
+    $empty_discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']], CustomPlugin2::class, ['Drupal\Tests\Component\Annotation']);
+    $this->assertEquals([], $empty_discovery->getDefinitions());
+  }
+
+}
+
+/**
+ * Custom plugin annotation.
+ *
+ * @Annotation
+ */
+class CustomPlugin extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The plugin title.
+   *
+   * @var string
+   *
+   * @ingroup plugin_translatable
+   */
+  public $title = '';
+
+}
+
+/**
+ * Custom plugin annotation.
+ *
+ * @Annotation
+ */
+class CustomPlugin2 extends Plugin {}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/AnnotationBaseTest.php b/core/tests/Drupal/Tests/Component/Annotation/AnnotationBaseTest.php
new file mode 100644
index 0000000000..91d5ae28c3
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/AnnotationBaseTest.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\AnnotationBase;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\AnnotationBase
+ * @group Annotation
+ */
+class AnnotationBaseTest extends TestCase {
+
+  /**
+   * @covers ::getProvider
+   * @covers ::setProvider
+   */
+  public function testSetProvider() {
+    $plugin = new AnnotationBaseStub();
+    $plugin->setProvider('example');
+    $this->assertEquals('example', $plugin->getProvider());
+  }
+
+  /**
+   * @covers ::getId
+   */
+  public function testGetId() {
+    $plugin = new AnnotationBaseStub();
+    // Doctrine sets the public prop directly.
+    $plugin->id = 'example';
+    $this->assertEquals('example', $plugin->getId());
+  }
+
+  /**
+   * @covers ::getClass
+   * @covers ::setClass
+   */
+  public function testSetClass() {
+    $plugin = new AnnotationBaseStub();
+    $plugin->setClass('example');
+    $this->assertEquals('example', $plugin->getClass());
+  }
+
+}
+/**
+ * {@inheritdoc}
+ */
+class AnnotationBaseStub extends AnnotationBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get() {}
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/DiscoveryTest1.php b/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/DiscoveryTest1.php
new file mode 100644
index 0000000000..e99ad5fb32
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/DiscoveryTest1.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace com\example\PluginNamespace;
+
+/**
+ * Provides a custom test plugin.
+ *
+ * @Plugin(
+ *   id = "discovery_test_1"
+ * )
+ * @CustomPlugin(
+ *   id = "discovery_test_1",
+ *   title = "Discovery test plugin"
+ * )
+ */
+class DiscoveryTest1 {}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/discoverytest2.yml b/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/discoverytest2.yml
new file mode 100644
index 0000000000..cd38150fc6
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/Fixtures/PluginNamespace/discoverytest2.yml
@@ -0,0 +1,2 @@
+# This should not be loaded by our annotated class discovery.
+id:discovery_test_2
diff --git a/core/tests/Drupal/Tests/Component/Annotation/MockFileFinderTest.php b/core/tests/Drupal/Tests/Component/Annotation/MockFileFinderTest.php
new file mode 100644
index 0000000000..697551c33a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/MockFileFinderTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\Reflection\MockFileFinder;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\Reflection\MockFileFinder
+ * @group Annotation
+ */
+class MockFileFinderTest extends TestCase {
+
+  /**
+   * @covers ::create
+   * @covers ::findFile
+   */
+  public function testFindFile() {
+    $tmp = MockFileFinder::create('testfilename.txt');
+    $this->assertEquals('testfilename.txt', $tmp->findFile('n/a'));
+    $this->assertEquals('testfilename.txt', $tmp->findFile('someclass'));
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php b/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php
index 62d3c84005..12732e110a 100644
--- a/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php
+++ b/core/tests/Drupal/Tests/Component/Annotation/Plugin/Discovery/AnnotationBridgeDecoratorTest.php
@@ -35,6 +35,9 @@ public function testGetDefinitions() {
 
 }
 
+/**
+ * {@inheritdoc}
+ */
 class TestAnnotation extends Plugin {
 
   /**
@@ -45,12 +48,17 @@ public function get() {
   }
 
 }
+
+/**
+ * {@inheritdoc}
+ */
 class ObjectDefinition extends PluginDefinition {
 
   /**
    * ObjectDefinition constructor.
    *
    * @param array $definition
+   *   An array of definition values.
    */
   public function __construct(array $definition) {
     foreach ($definition as $property => $value) {
diff --git a/core/tests/Drupal/Tests/Component/Annotation/PluginIdTest.php b/core/tests/Drupal/Tests/Component/Annotation/PluginIdTest.php
new file mode 100644
index 0000000000..f115de34f1
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/PluginIdTest.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\PluginID;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\PluginId
+ * @group Annotation
+ */
+class PluginIdTest extends TestCase {
+
+  /**
+   * @covers ::get
+   */
+  public function testGet() {
+    // Assert plugin starts empty regardless of constructor.
+    $plugin = new PluginID([
+      'foo' => 'bar',
+      'biz' => [
+        'baz' => 'boom',
+      ],
+      'nestedAnnotation' => new PluginID([
+        'foo' => 'bar',
+      ]),
+      'value' => 'biz',
+    ]);
+    $this->assertEquals([
+      'id' => NULL,
+      'class' => NULL,
+      'provider' => NULL,
+    ], $plugin->get());
+
+    // Set values and ensure we can retrieve them.
+    $plugin->value = 'foo';
+    $plugin->setClass('bar');
+    $plugin->setProvider('baz');
+    $this->assertEquals([
+      'id' => 'foo',
+      'class' => 'bar',
+      'provider' => 'baz',
+    ], $plugin->get());
+  }
+
+  /**
+   * @covers ::getId
+   */
+  public function testGetId() {
+    $plugin = new PluginID([]);
+    $plugin->value = 'example';
+    $this->assertEquals('example', $plugin->getId());
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php b/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php
new file mode 100644
index 0000000000..d942764005
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Drupal\Tests\Component\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\Annotation\Plugin
+ * @group Annotation
+ */
+class PluginTest extends TestCase {
+
+  /**
+   * @covers ::__construct
+   * @covers ::parse
+   * @covers ::get
+   */
+  public function testGet() {
+    // Assert all values are accepted through constructor and default value is
+    // used for non existent but defined property.
+    $plugin = new PluginStub([
+      'foo' => 'bar',
+      'biz' => [
+        'baz' => 'boom',
+      ],
+      'nestedAnnotation' => new Plugin([
+        'foo' => 'bar',
+      ]),
+    ]);
+    $this->assertEquals([
+      // This property wasn't in our definition but is defined as a property on
+      // our plugin class.
+      'defaultProperty' => 'testvalue',
+      'foo' => 'bar',
+      'biz' => [
+        'baz' => 'boom',
+      ],
+      'nestedAnnotation' => [
+        'foo' => 'bar',
+      ],
+    ], $plugin->get());
+
+    // Without default properties, we get a completely empty plugin definition.
+    $plugin = new Plugin([]);
+    $this->assertEquals([], $plugin->get());
+  }
+
+  /**
+   * @covers ::getProvider
+   */
+  public function testGetProvider() {
+    $plugin = new Plugin(['provider' => 'example']);
+    $this->assertEquals('example', $plugin->getProvider());
+  }
+
+  /**
+   * @covers ::setProvider
+   */
+  public function testSetProvider() {
+    $plugin = new Plugin([]);
+    $plugin->setProvider('example');
+    $this->assertEquals('example', $plugin->getProvider());
+  }
+
+  /**
+   * @covers ::getId
+   */
+  public function testGetId() {
+    $plugin = new Plugin(['id' => 'example']);
+    $this->assertEquals('example', $plugin->getId());
+  }
+
+  /**
+   * @covers ::getClass
+   */
+  public function testGetClass() {
+    $plugin = new Plugin(['class' => 'example']);
+    $this->assertEquals('example', $plugin->getClass());
+  }
+
+  /**
+   * @covers ::setClass
+   */
+  public function testSetClass() {
+    $plugin = new Plugin([]);
+    $plugin->setClass('example');
+    $this->assertEquals('example', $plugin->getClass());
+  }
+
+}
+/**
+ * {@inheritdoc}
+ */
+class PluginStub extends Plugin {
+  protected $defaultProperty = 'testvalue';
+
+}
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 5139f97730..032b8c7e9d 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -33,6 +33,13 @@
   protected $root;
 
   /**
+   * Original file cache configuration from before we disable it.
+   *
+   * @var array
+   */
+  protected $originalFileCacheConfig;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -43,6 +50,7 @@ protected function setUp() {
 
     // Ensure that the NullFileCache implementation is used for the FileCache as
     // unit tests should not be relying on caches implicitly.
+    $this->originalFileCacheConfig = FileCacheFactory::getConfiguration();
     FileCacheFactory::setConfiguration([FileCacheFactory::DISABLE_CACHE => TRUE]);
     // Ensure that FileCacheFactory has a prefix.
     FileCacheFactory::setPrefix('prefix');
@@ -51,6 +59,14 @@ protected function setUp() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    FileCacheFactory::setConfiguration($this->originalFileCacheConfig);
+    parent::tearDown();
+  }
+
+  /**
    * Generates a unique random string containing letters and numbers.
    *
    * @param int $length
