diff --git a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php
index b04e39d..e726ed6 100644
--- a/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php
+++ b/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php
@@ -8,6 +8,7 @@
 namespace Drupal\Component\Annotation\Plugin\Discovery;
 
 use Drupal\Component\Annotation\AnnotationInterface;
+use Drupal\Component\Plugin\Discovery\DiscoveryBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Component\Annotation\Reflection\MockFileFinder;
 use Doctrine\Common\Annotations\SimpleAnnotationReader;
@@ -17,7 +18,7 @@
 /**
  * Defines a discovery mechanism to find annotated plugins in PSR-0 namespaces.
  */
-class AnnotatedClassDiscovery implements DiscoveryInterface {
+class AnnotatedClassDiscovery extends DiscoveryBase implements DiscoveryInterface {
 
   /**
    * The namespaces within which to find plugin classes.
@@ -76,14 +77,6 @@ protected function getAnnotationReader() {
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    $plugins = $this->getDefinitions();
-    return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : NULL;
-  }
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
index 027c59a..417d5c8 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
@@ -39,10 +39,15 @@ public function __construct(DiscoveryInterface $decorated) {
    *   Thrown if the 'derivative' class specified in the plugin definition does
    *   not implement \Drupal\Component\Plugin\Derivative\DerivativeInterface.
    */
-  public function getDefinition($plugin_id) {
-    $plugin_definition = $this->decorated->getDefinition($plugin_id);
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    // This check is only for derivative plugins that have explicitly provided
+    // an ID. This is not common, and can be expected to fail. Therefore, opt
+    // out of the thrown exception, which will be handled when checking the
+    // $base_plugin_id.
+    $plugin_definition = $this->decorated->getDefinition($plugin_id, FALSE);
+
     list($base_plugin_id, $derivative_id) = $this->decodePluginId($plugin_id);
-    $base_plugin_definition = $this->decorated->getDefinition($base_plugin_id);
+    $base_plugin_definition = $this->decorated->getDefinition($base_plugin_id, $exception_on_invalid);
     if ($base_plugin_definition) {
       $derivative_fetcher = $this->getDerivativeFetcher($base_plugin_id, $base_plugin_definition);
       if ($derivative_fetcher) {
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryBase.php b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryBase.php
new file mode 100644
index 0000000..42907c3
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryBase.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\Discovery\DiscoveryBase.
+ */
+
+namespace Drupal\Component\Plugin\Discovery;
+
+use Drupal\Component\Plugin\Exception\UnknownPluginException;
+
+/**
+ * Contains a base class for discovery.
+ *
+ * @todo Replace with a trait.
+ */
+abstract class DiscoveryBase implements DiscoveryInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    $definitions = $this->getDefinitions();
+    return $this->doGetDefinition($definitions, $plugin_id, $exception_on_invalid);
+  }
+
+  /**
+   * Gets a specific plugin definition.
+   *
+   * @param array $definitions
+   *   An array of the available plugin definitions.
+   * @param string $plugin_id
+   *   A plugin id.
+   * @param bool $exception_on_invalid
+   *   (optional) If TRUE, an invalid plugin ID will throw an exception.
+   *   Defaults to FALSE.
+   *
+   * @return array|null
+   *   A plugin definition, or NULL if the plugin ID is invalid and
+   *   $exception_on_invalid is TRUE.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\UnknownPluginException
+   *   Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
+   */
+  protected function doGetDefinition(array $definitions, $plugin_id, $exception_on_invalid) {
+    // Avoid using a ternary that would create a copy of the array.
+    if (isset($definitions[$plugin_id])) {
+      return $definitions[$plugin_id];
+    }
+    elseif (!$exception_on_invalid) {
+      return NULL;
+    }
+
+    throw new UnknownPluginException($plugin_id, sprintf('The "%s" plugin does not exist.', $plugin_id));
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedBase.php b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedBase.php
new file mode 100644
index 0000000..be151d5
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedBase.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\Discovery\DiscoveryCachedBase.
+ */
+
+namespace Drupal\Component\Plugin\Discovery;
+
+/**
+ * Contains a base class for statically cached discovery.
+ *
+ * @todo Replace with a trait.
+ */
+abstract class DiscoveryCachedBase extends DiscoveryBase {
+
+  /**
+   * Cached definitions array.
+   *
+   * @var array
+   */
+  protected $definitions;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    // Fetch definitions if they're not loaded yet.
+    if (!isset($this->definitions)) {
+      $this->getDefinitions();
+    }
+
+    return $this->doGetDefinition($this->definitions, $plugin_id, $exception_on_invalid);
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php
index aaf4743..dc4adef 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryInterface.php
@@ -18,11 +18,18 @@
    *
    * @param string $plugin_id
    *   A plugin id.
+   * @param bool $exception_on_invalid
+   *   (optional) If TRUE, an invalid plugin ID will throw an exception.
+   *   Defaults to FALSE.
    *
    * @return array|null
-   *   A plugin definition, or NULL if no definition was found for $plugin_id.
+   *   A plugin definition, or NULL if the plugin ID is invalid and
+   *   $exception_on_invalid is TRUE.
+   *
+   * @throws \InvalidArgumentException
+   *   Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
    */
-  public function getDefinition($plugin_id);
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE);
 
   /**
    * Gets the definition of all plugins for this type.
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/ProcessDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/ProcessDecorator.php
index fee6518..a262fa2 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/ProcessDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/ProcessDecorator.php
@@ -13,7 +13,7 @@
  * Example use cases include adding in default values for a definition, or
  * providing a backwards compatibility layer for renamed definition properties.
  */
-class ProcessDecorator implements DiscoveryInterface {
+class ProcessDecorator extends DiscoveryBase implements DiscoveryInterface {
 
   /**
    * The Discovery object being decorated.
@@ -47,16 +47,6 @@ public function __construct(DiscoveryInterface $decorated, $process_callback) {
   }
 
   /**
-   * Implements \Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    $definitions = $this->getDefinitions();
-    if (isset($definitions[$plugin_id])) {
-      return $definitions[$plugin_id];
-    }
-  }
-
-  /**
    * Implements \Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
index de74fb5..2eac43e 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
@@ -11,7 +11,7 @@
  * A discovery mechanism that allows plugin definitions to be manually
  * registered rather than actively discovered.
  */
-class StaticDiscovery implements DiscoveryInterface {
+class StaticDiscovery extends DiscoveryCachedBase implements DiscoveryInterface {
 
   /**
    * The array of plugin definitions, keyed by plugin id.
@@ -21,13 +21,6 @@ class StaticDiscovery implements DiscoveryInterface {
   protected $definitions = array();
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
-   */
-  public function getDefinition($base_plugin_id) {
-    return isset($this->definitions[$base_plugin_id]) ? $this->definitions[$base_plugin_id] : NULL;
-  }
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
index c92ae8d..fbad2dd 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
@@ -41,14 +41,14 @@ public function __construct(DiscoveryInterface $decorated, $registerDefinitions
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
+   * {@inheritdoc}
    */
-  public function getDefinition($base_plugin_id) {
+  public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
     if (isset($this->registerDefinitions)) {
       call_user_func($this->registerDefinitions);
     }
     $this->definitions += $this->decorated->getDefinitions();
-    return parent::getDefinition($base_plugin_id);
+    return parent::getDefinition($base_plugin_id, $exception_on_invalid);
   }
 
   /**
diff --git a/core/lib/Drupal/Component/Plugin/PluginManagerBase.php b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
index 1fe5160..5122777 100644
--- a/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
+++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
@@ -38,8 +38,8 @@
   /**
    * {@inheritdoc}
    */
-  public function getDefinition($plugin_id) {
-    return $this->discovery->getDefinition($plugin_id);
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    return $this->discovery->getDefinition($plugin_id, $exception_on_invalid);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php
index 7716a5b..3862fdd 100644
--- a/core/lib/Drupal/Core/Config/TypedConfigManager.php
+++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php
@@ -145,9 +145,9 @@ public function createInstance($plugin_id, array $configuration, $name = NULL, $
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
+   * {@inheritdoc}
    */
-  public function getDefinition($base_plugin_id) {
+  public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
     $definitions = $this->getDefinitions();
     if (isset($definitions[$base_plugin_id])) {
       $type = $base_plugin_id;
@@ -164,7 +164,7 @@ public function getDefinition($base_plugin_id) {
     $definition = $definitions[$type];
     // Check whether this type is an extension of another one and compile it.
     if (isset($definition['type'])) {
-      $merge = $this->getDefinition($definition['type']);
+      $merge = $this->getDefinition($definition['type'], $exception_on_invalid);
       $definition = NestedArray::mergeDeep($merge, $definition);
       // Unset type so we try the merge only once per type.
       unset($definition['type']);
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 8f7e929..2dadd30 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -162,8 +162,8 @@ public function clearCachedDefinitions() {
   /**
    * {@inheritdoc}
    */
-  public function getDefinition($entity_type_id, $exception_on_invalid = FALSE) {
-    if (($entity_type = parent::getDefinition($entity_type_id)) && class_exists($entity_type->getClass())) {
+  public function getDefinition($entity_type_id, $exception_on_invalid = TRUE) {
+    if (($entity_type = parent::getDefinition($entity_type_id, FALSE)) && class_exists($entity_type->getClass())) {
       return $entity_type;
     }
     elseif (!$exception_on_invalid) {
@@ -177,7 +177,7 @@ public function getDefinition($entity_type_id, $exception_on_invalid = FALSE) {
    * {@inheritdoc}
    */
   public function hasController($entity_type, $controller_type) {
-    if ($definition = $this->getDefinition($entity_type)) {
+    if ($definition = $this->getDefinition($entity_type, FALSE)) {
       return $definition->hasControllerClass($controller_type);
     }
     return FALSE;
@@ -202,7 +202,7 @@ public function getListController($entity_type) {
    */
   public function getFormController($entity_type, $operation) {
     if (!isset($this->controllers['form'][$operation][$entity_type])) {
-      if (!$class = $this->getDefinition($entity_type, TRUE)->getFormClass($operation)) {
+      if (!$class = $this->getDefinition($entity_type)->getFormClass($operation)) {
         throw new InvalidPluginDefinitionException($entity_type, sprintf('The "%s" entity type did not specify a "%s" form class.', $entity_type, $operation));
       }
       if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($class))) {
@@ -252,7 +252,7 @@ public function getAccessController($entity_type) {
    */
   public function getController($entity_type, $controller_type, $controller_class_getter = NULL) {
     if (!isset($this->controllers[$controller_type][$entity_type])) {
-      $definition = $this->getDefinition($entity_type, TRUE);
+      $definition = $this->getDefinition($entity_type);
       if ($controller_class_getter) {
         $class = $definition->{$controller_class_getter}();
       }
@@ -299,7 +299,7 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $
    * {@inheritdoc}
    */
   public function getAdminRouteInfo($entity_type, $bundle) {
-    if (($entity_info = $this->getDefinition($entity_type)) && $admin_form = $entity_info->getLinkTemplate('admin-form')) {
+    if (($entity_info = $this->getDefinition($entity_type, FALSE)) && $admin_form = $entity_info->getLinkTemplate('admin-form')) {
       return array(
         'route_name' => $admin_form,
         'route_parameters' => array(
@@ -322,7 +322,7 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) {
       else {
         // @todo: Refactor to allow for per-bundle overrides.
         // See https://drupal.org/node/2114707.
-        $entity_info = $this->getDefinition($entity_type);
+        $entity_info = $this->getDefinition($entity_type, TRUE);
         $class = $entity_info->getClass();
 
         $this->entityFieldInfo[$entity_type] = array(
diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
index 35c7280..06c5718 100644
--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -244,28 +244,16 @@ public function getBundleInfo($entity_type);
   public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array());
 
   /**
-   * Returns the entity type info for a specific entity type.
-   *
-   * @param string $entity_type_id
-   *   The ID of the entity type.
-   * @param bool $exception_on_invalid
-   *   (optional) If TRUE, an invalid entity type ID will throw an exception.
-   *   Defaults to FALSE.
+   * {@inheritdoc}
    *
    * @return \Drupal\Core\Entity\EntityTypeInterface|null
-   *   Returns the entity type object, or NULL if the entity type ID is invalid
-   *   and $exception_on_invalid is TRUE.
-   *
-   * @throws \InvalidArgumentException
-   *   Thrown if $entity_type_id is invalid and $exception_on_invalid is TRUE.
    */
-  public function getDefinition($entity_type_id, $exception_on_invalid = FALSE);
+  public function getDefinition($entity_type_id, $exception_on_invalid = TRUE);
 
   /**
-   * Returns an array of entity type info, keyed by entity type name.
+   * {@inheritdoc}
    *
    * @return \Drupal\Core\Entity\EntityTypeInterface[]
-   *   An array of entity type objects.
    */
   public function getDefinitions();
 
diff --git a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php
index 86e5552..2ef364b 100644
--- a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php
+++ b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php
@@ -72,7 +72,7 @@ public function processDefinition(&$definition, $plugin_id) {
    *   definition, or an empty array if type or settings are undefined.
    */
   public function getDefaultSettings($type) {
-    $info = $this->getDefinition($type);
+    $info = $this->getDefinition($type, FALSE);
     return isset($info['settings']) ? $info['settings'] : array();
   }
 
@@ -87,7 +87,7 @@ public function getDefaultSettings($type) {
    *   definition, or an empty array if type or settings are undefined.
    */
   public function getDefaultInstanceSettings($type) {
-    $info = $this->getDefinition($type);
+    $info = $this->getDefinition($type, FALSE);
     return isset($info['instance_settings']) ? $info['instance_settings'] : array();
   }
 
diff --git a/core/lib/Drupal/Core/Field/FormatterPluginManager.php b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
index 18a7789..ae0b38b 100644
--- a/core/lib/Drupal/Core/Field/FormatterPluginManager.php
+++ b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
@@ -113,7 +113,7 @@ public function getInstance(array $options) {
     // Switch back to default formatter if either:
     // - $type_info doesn't exist (the widget type is unknown),
     // - the field type is not allowed for the widget.
-    $definition = $this->getDefinition($configuration['type']);
+    $definition = $this->getDefinition($configuration['type'], FALSE);
     if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
       // Grab the default widget for the field type.
       $field_type_definition = $this->fieldTypeManager->getDefinition($field_type);
@@ -196,7 +196,7 @@ public function getOptions($field_type = NULL) {
    *   definition, or an empty array if type or settings are undefined.
    */
   public function getDefaultSettings($type) {
-    $info = $this->getDefinition($type);
+    $info = $this->getDefinition($type, FALSE);
     return isset($info['settings']) ? $info['settings'] : array();
   }
 
diff --git a/core/lib/Drupal/Core/Field/WidgetPluginManager.php b/core/lib/Drupal/Core/Field/WidgetPluginManager.php
index 8d010e7..89a5b85 100644
--- a/core/lib/Drupal/Core/Field/WidgetPluginManager.php
+++ b/core/lib/Drupal/Core/Field/WidgetPluginManager.php
@@ -99,7 +99,7 @@ public function getInstance(array $options) {
     // Switch back to default widget if either:
     // - $type_info doesn't exist (the widget type is unknown),
     // - the field type is not allowed for the widget.
-    $definition = $this->getDefinition($configuration['type']);
+    $definition = $this->getDefinition($configuration['type'], FALSE);
     if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
       // Grab the default widget for the field type.
       $field_type_definition = $this->fieldTypeManager->getDefinition($field_type);
@@ -200,7 +200,7 @@ public function getOptions($field_type = NULL) {
    *   definition, or an empty array if type or settings are undefined.
    */
   public function getDefaultSettings($type) {
-    $info = $this->getDefinition($type);
+    $info = $this->getDefinition($type, FALSE);
     return isset($info['settings']) ? $info['settings'] : array();
   }
 
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index 6cbabf8..e84f579 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Plugin;
 
 use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
+use Drupal\Component\Plugin\Exception\UnknownPluginException;
 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\PluginManagerInterface;
@@ -163,7 +164,9 @@ protected function alterInfo(ModuleHandlerInterface $module_handler, $alter_hook
   /**
    * {@inheritdoc}
    */
-  public function getDefinition($plugin_id) {
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    // @todo When \Drupal\Component\Plugin\Discovery\DiscoveryCachedBase is
+    //   converted to a trait, use that and remove this implementation.
     // Fetch definitions if they're not loaded yet.
     if (!isset($this->definitions)) {
       $this->getDefinitions();
@@ -172,7 +175,11 @@ public function getDefinition($plugin_id) {
     if (isset($this->definitions[$plugin_id])) {
       return $this->definitions[$plugin_id];
     }
-    return array();
+    elseif (!$exception_on_invalid) {
+      return NULL;
+    }
+
+    throw new UnknownPluginException($plugin_id, sprintf('The "%s" plugin does not exist.', $plugin_id));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AlterDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/AlterDecorator.php
index c81894e..58b273f 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/AlterDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/AlterDecorator.php
@@ -7,12 +7,13 @@
 
 namespace Drupal\Core\Plugin\Discovery;
 
+use Drupal\Component\Plugin\Discovery\DiscoveryBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 
 /**
  * Enables altering of discovered plugin definitions.
  */
-class AlterDecorator implements DiscoveryInterface {
+class AlterDecorator extends DiscoveryBase implements DiscoveryInterface {
   /**
    * The name of the alter hook that will be implemented by this discovery instance.
    *
@@ -43,15 +44,6 @@ public function __construct(DiscoveryInterface $decorated, $hook) {
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    $definitions = $this->getDefinitions();
-    return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
-  }
-
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
index 9d3cc9a..a5f6c40 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
@@ -8,13 +8,14 @@
 namespace Drupal\Core\Plugin\Discovery;
 
 use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
+use Drupal\Component\Plugin\Discovery\DiscoveryCachedBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Cache\Cache;
 
 /**
  * Enables static and persistent caching of discovered plugin definitions.
  */
-class CacheDecorator implements CachedDiscoveryInterface {
+class CacheDecorator extends DiscoveryCachedBase implements CachedDiscoveryInterface {
 
   /**
    * The cache key used to store the definition list.
@@ -84,28 +85,6 @@ public function __construct(DiscoveryInterface $decorated, $cache_key, $cache_bi
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    // Optimize for fast access to definitions if they are already in memory.
-    if (isset($this->definitions)) {
-      // Avoid using a ternary that would create a copy of the array.
-      if (isset($this->definitions[$plugin_id])) {
-        return $this->definitions[$plugin_id];
-      }
-      else {
-        return;
-      }
-    }
-
-    $definitions = $this->getDefinitions();
-    // Avoid using a ternary that would create a copy of the array.
-    if (isset($definitions[$plugin_id])) {
-      return $definitions[$plugin_id];
-    }
-  }
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/HookDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/HookDiscovery.php
index 035d402..3b93078 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/HookDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/HookDiscovery.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\Core\Plugin\Discovery;
 
+use Drupal\Component\Plugin\Discovery\DiscoveryBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 
 /**
  * Provides a hook-based plugin discovery class.
  */
-class HookDiscovery implements DiscoveryInterface {
+class HookDiscovery extends DiscoveryBase implements DiscoveryInterface {
 
   /**
    * The name of the hook that will be implemented by this discovery instance.
@@ -44,14 +45,6 @@ function __construct(ModuleHandlerInterface $module_handler, $hook) {
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    $plugins = $this->getDefinitions();
-    return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : NULL;
-  }
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DicoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
index 4733c8c..8899c40 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
@@ -7,12 +7,13 @@
 
 namespace Drupal\Core\Plugin\Discovery;
 
+use Drupal\Component\Plugin\Discovery\DiscoveryBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 
 /**
  * Allows info hook implementations to enhance discovered plugin definitions.
  */
-class InfoHookDecorator implements DiscoveryInterface {
+class InfoHookDecorator extends DiscoveryBase implements DiscoveryInterface {
 
   /**
    * The Discovery object being decorated.
@@ -42,14 +43,6 @@ public function __construct(DiscoveryInterface $decorated, $hook) {
   }
 
   /**
-   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
-   */
-  public function getDefinition($plugin_id) {
-    $definitions = $this->getDefinitions();
-    return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
-  }
-
-  /**
    * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
    */
   public function getDefinitions() {
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscovery.php
index 516704b..6f32328 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscovery.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\Core\Plugin\Discovery;
 
+use Drupal\Component\Plugin\Discovery\DiscoveryBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Component\Discovery\YamlDiscovery as ComponentYamlDiscovery;
 
 /**
  * Allows YAML files to define plugin definitions.
  */
-class YamlDiscovery implements DiscoveryInterface {
+class YamlDiscovery extends DiscoveryBase implements DiscoveryInterface {
 
   /**
    * YAML file discovery and parsing handler.
@@ -38,14 +39,6 @@ function __construct($name, array $directories) {
   /**
    * {@inheritdoc}
    */
-  public function getDefinition($plugin_id) {
-    $definitions = $this->getDefinitions();
-    return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getDefinitions() {
     $plugins = $this->discovery->findAll();
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
index c5a9cf7..28ea82c 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
@@ -54,7 +54,7 @@ public function getPropertyDefinitions() {
       static::$propertyDefinitions['value'] = DataDefinition::create('datetime_iso8601')
         ->setLabel(t('Date value'));
 
-      static::$propertyDefinitions['date'] = DataDefinition::create('datetime_computed')
+      static::$propertyDefinitions['date'] = DataDefinition::create('any')
         ->setLabel(t('Computed date'))
         ->setDescription(t('The computed DateTime object.'))
         ->setComputed(TRUE)
diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php
index 827c06f..b89e61e 100644
--- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php
+++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php
@@ -64,7 +64,7 @@ protected function validateAndUpcastRequestAttributes(Request $request) {
     if (!is_object($entity = $request->attributes->get('entity'))) {
       $entity_id = $entity;
       $entity_type = $request->attributes->get('entity_type');
-      if (!$entity_type || !$this->entityManager->getDefinition($entity_type)) {
+      if (!$entity_type || !$this->entityManager->getDefinition($entity_type, FALSE)) {
         throw new NotFoundHttpException();
       }
       $entity = $this->entityManager->getStorageController($entity_type)->load($entity_id);
diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
index 9de7347..d9c6605 100644
--- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
+++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
@@ -64,7 +64,7 @@ protected function validateAndUpcastRequestAttributes(Request $request) {
     if (!is_object($entity = $request->attributes->get('entity'))) {
       $entity_id = $entity;
       $entity_type = $request->attributes->get('entity_type');
-      if (!$entity_type || !$this->entityManager->getDefinition($entity_type)) {
+      if (!$entity_type || !$this->entityManager->getDefinition($entity_type, FALSE)) {
         throw new NotFoundHttpException();
       }
       $entity = $this->entityManager->getStorageController($entity_type)->load($entity_id);
diff --git a/core/modules/edit/lib/Drupal/edit/EditController.php b/core/modules/edit/lib/Drupal/edit/EditController.php
index 2825383..c2c0e83 100644
--- a/core/modules/edit/lib/Drupal/edit/EditController.php
+++ b/core/modules/edit/lib/Drupal/edit/EditController.php
@@ -108,7 +108,7 @@ public function metadata(Request $request) {
       list($entity_type, $entity_id, $field_name, $langcode, $view_mode) = explode('/', $field);
 
       // Load the entity.
-      if (!$entity_type || !$this->entityManager()->getDefinition($entity_type)) {
+      if (!$entity_type || !$this->entityManager()->getDefinition($entity_type, FALSE)) {
         throw new NotFoundHttpException();
       }
       $entity = $this->entityManager()->getStorageController($entity_type)->load($entity_id);
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index f05fd02..b075aac 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -198,7 +198,7 @@ function entity_reference_query_entity_reference_alter(AlterableInterface $query
  */
 function entity_reference_create_instance($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = array(), $cardinality = 1) {
   // If a field type we know should exist isn't found, clear the field cache.
-  if (!\Drupal::service('plugin.manager.field.field_type')->getDefinition('entity_reference')) {
+  if (!\Drupal::service('plugin.manager.field.field_type')->getDefinition('entity_reference', FALSE)) {
     field_cache_clear();
   }
 
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
index 172aee4..f1349b9 100644
--- a/core/modules/field/field.views.inc
+++ b/core/modules/field/field.views.inc
@@ -67,7 +67,7 @@ function field_views_data_alter(&$data) {
  */
 function _field_views_is_sql_entity_type(FieldInterface $field) {
   $entity_manager = \Drupal::entityManager();
-  if ($entity_manager->getDefinition($field->entity_type) && $entity_manager->getStorageController($field->entity_type) instanceof FieldableDatabaseStorageController) {
+  if ($entity_manager->getDefinition($field->entity_type, FALSE) && $entity_manager->getStorageController($field->entity_type) instanceof FieldableDatabaseStorageController) {
     return TRUE;
   }
 }
@@ -112,7 +112,7 @@ function field_views_field_default_views_data(FieldInterface $field) {
   $data = array();
 
   // Check the field type is available.
-  if (!\Drupal::service('plugin.manager.field.field_type')->getDefinition($field->getType())) {
+  if (!\Drupal::service('plugin.manager.field.field_type')->getDefinition($field->getType(), FALSE)) {
     return $data;
   }
   // Check the field has instances.
diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
index 61663e8..ecc71c5 100644
--- a/core/modules/field/lib/Drupal/field/FieldInfo.php
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -438,7 +438,7 @@ public function getBundleInstances($entity_type, $bundle) {
     $fields = array();
 
     // Do not return anything for unknown entity types.
-    if (\Drupal::entityManager()->getDefinition($entity_type) && !empty($field_map[$entity_type])) {
+    if (\Drupal::entityManager()->getDefinition($entity_type, FALSE) && !empty($field_map[$entity_type])) {
 
       // Collect names of fields and instances involved in the bundle, using the
       // field map. The field map is already filtered to non-deleted fields and
diff --git a/core/modules/field/tests/modules/field_test/field_test.info.yml b/core/modules/field/tests/modules/field_test/field_test.info.yml
index b05dab5..b43a394 100644
--- a/core/modules/field/tests/modules/field_test/field_test.info.yml
+++ b/core/modules/field/tests/modules/field_test/field_test.info.yml
@@ -5,3 +5,5 @@ core: 8.x
 package: Testing
 version: VERSION
 hidden: true
+dependencies:
+  - entity_test
diff --git a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
index 1a1fcc0..7362b9a 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
@@ -47,10 +47,14 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
   /**
    * {@inheritdoc}
    */
-  public function getDefinition($plugin_id) {
-    $plugins = $this->getDefinitions();
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    $definitions = $this->getDefinitions();
+    // Avoid using a ternary that would create a copy of the array.
+    if (isset($definitions[$plugin_id])) {
+      return $definitions[$plugin_id];
+    }
     // If the requested filter is missing, use the null filter.
-    return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : $plugins['filter_null'];
+    return $definitions['filter_null'];
   }
 
 }
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index e13002a..0491320 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -92,7 +92,7 @@ function forum_install() {
  * Implements hook_module_preinstall().
  */
 function forum_module_preinstall($module) {
-  $list_boolean = \Drupal::service('plugin.manager.field.field_type')->getDefinition('list_boolean');
+  $list_boolean = \Drupal::service('plugin.manager.field.field_type')->getDefinition('list_boolean', FALSE);
   if (empty($list_boolean) && $module == 'forum') {
     // Make sure that the list_boolean field type is available before our
     // default config is installed.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php
index b305d28..e1ad8fa 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorTest.php
@@ -124,7 +124,7 @@ public function testClearCachedDefinitions() {
     $this->discovery->setDefinition('banana', $this->expectedDefinitions['banana']);
 
     // Check that the new definition is not found.
-    $definition = $this->discovery->getDefinition('banana');
+    $definition = $this->discovery->getDefinition('banana', FALSE);
     $this->assertNull($definition, 'Newly added definition is not found.');
 
     // Clear cached definitions, and check that the new definition is found.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/DerivativeTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/DerivativeTest.php
index 4456808..8feeff6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/DerivativeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/DerivativeTest.php
@@ -35,8 +35,8 @@ function testDerivativeDecorator() {
     // Ensure that NULL is returned as the definition of a non-existing base
     // plugin, a non-existing derivative plugin, or a base plugin that may not
     // be used without deriving.
-    $this->assertIdentical($this->mockBlockManager->getDefinition('non_existing'), NULL, 'NULL returned as the definition of a non-existing base plugin.');
-    $this->assertIdentical($this->mockBlockManager->getDefinition('menu:non_existing'), NULL, 'NULL returned as the definition of a non-existing derivative plugin.');
-    $this->assertIdentical($this->mockBlockManager->getDefinition('menu'), NULL, 'NULL returned as the definition of a base plugin that may not be used without deriving.');
+    $this->assertIdentical($this->mockBlockManager->getDefinition('non_existing', FALSE), NULL, 'NULL returned as the definition of a non-existing base plugin.');
+    $this->assertIdentical($this->mockBlockManager->getDefinition('menu:non_existing', FALSE), NULL, 'NULL returned as the definition of a non-existing derivative plugin.');
+    $this->assertIdentical($this->mockBlockManager->getDefinition('menu', FALSE), NULL, 'NULL returned as the definition of a base plugin that may not be used without deriving.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/DiscoveryTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/DiscoveryTestBase.php
index 20a574a..577d7bc 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/DiscoveryTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/Discovery/DiscoveryTestBase.php
@@ -56,7 +56,7 @@ function testDiscoveryInterface() {
     $this->assertIdentical($this->emptyDiscovery->getDefinitions(), array(), 'array() returned if no plugin definitions are found.');
 
     // Ensure that NULL is returned as the definition of a non-existing plugin.
-    $this->assertIdentical($this->emptyDiscovery->getDefinition('non_existing'), NULL, 'NULL returned as the definition of a non-existing plugin.');
+    $this->assertIdentical($this->emptyDiscovery->getDefinition('non_existing', FALSE), NULL, 'NULL returned as the definition of a non-existing plugin.');
   }
 }
 
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.install b/core/modules/system/tests/modules/entity_test/entity_test.install
index a03acf0..f480676 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.install
+++ b/core/modules/system/tests/modules/entity_test/entity_test.install
@@ -32,7 +32,7 @@ function entity_test_install() {
     ))->save();
 
     entity_get_form_display($entity_type, $entity_type, 'default')
-      ->setComponent('field_test_text', array('type' => 'text_text'))
+      ->setComponent('field_test_text', array('type' => 'text_textfield'))
       ->save();
   }
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
index 32f6414..a6b5196 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
@@ -785,7 +785,7 @@ protected function defaultDisplayOptions() {
     // Load the plugin ID and module.
     $base_field = $data['table']['base']['field'];
     $display_options['fields'][$base_field]['plugin_id'] = $data[$base_field]['field']['id'];
-    if ($definition = Views::pluginManager('field')->getDefinition($display_options['fields'][$base_field]['plugin_id'])) {
+    if ($definition = Views::pluginManager('field')->getDefinition($display_options['fields'][$base_field]['plugin_id'], FALSE)) {
       $display_options['fields'][$base_field]['provider'] = isset($definition['provider']) ? $definition['provider'] : 'views';
     }
 
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php
index 6b28d36..4e4d0ec 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php
@@ -246,7 +246,7 @@ public function testInvalidDisplayPlugins() {
 
     $this->drupalGet('test_display_invalid');
     $this->assertResponse(200);
-    $this->assertText(t('The plugin (invalid) did not specify an instance class.'));
+    $this->assertText('The "invalid" plugin does not exist.');
 
     // Rebuild the router, and ensure that the path is not accessible anymore.
     views_invalidate_cache();
@@ -276,7 +276,7 @@ public function testInvalidDisplayPlugins() {
     // plugin warning message.
     $this->drupalGet('<front>');
     $this->assertResponse(200);
-    $this->assertText(t('The plugin (invalid) did not specify an instance class.'));
+    $this->assertText('The "invalid" plugin does not exist.');
     $this->assertNoBlockAppears($block);
   }
 
diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php
index 88ebefc..e455316 100644
--- a/core/modules/views/lib/Drupal/views/ViewExecutable.php
+++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php
@@ -2005,7 +2005,7 @@ public function addHandler($display_id, $type, $table, $field, $options = array(
     $data = Views::viewsData()->get($table);
     if (isset($data[$field][$handler_type]['id'])) {
       $fields[$id]['plugin_id'] = $data[$field][$handler_type]['id'];
-      if ($definition = Views::pluginManager($handler_type)->getDefinition($fields[$id]['plugin_id'])) {
+      if ($definition = Views::pluginManager($handler_type)->getDefinition($fields[$id]['plugin_id'], FALSE)) {
         $fields[$id]['provider'] = isset($definition['provider']) ? $definition['provider'] : 'views';
       }
     }
diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
index 534f824..bd4dc60 100644
--- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
+++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
@@ -42,6 +42,7 @@ public function testBuildRowEntityList() {
       ->will($this->returnValueMap(array(
         array(
           'default',
+          TRUE,
           array(
             'id' => 'default',
             'title' => 'Master',
@@ -51,6 +52,7 @@ public function testBuildRowEntityList() {
         ),
         array(
           'page',
+          TRUE,
           array(
             'id' => 'page',
             'title' => 'Page',
@@ -63,6 +65,7 @@ public function testBuildRowEntityList() {
         ),
         array(
           'embed',
+          TRUE,
           array(
             'id' => 'embed',
             'title' => 'embed',
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 24df3b7..cbccf03 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\Core\Entity;
 
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Component\Plugin\Exception\UnknownPluginException;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
@@ -149,16 +150,22 @@ protected function tearDown() {
    */
   protected function setUpEntityManager($definitions = array()) {
     $class = $this->getMockClass('Drupal\Core\Entity\EntityInterface');
-    $definitions_map = array();
     foreach ($definitions as $entity_type_id => $entity_type) {
       $entity_type->expects($this->any())
         ->method('getClass')
         ->will($this->returnValue($class));
-      $definitions_map[] = array($entity_type_id, $entity_type);
     }
     $this->discovery->expects($this->any())
       ->method('getDefinition')
-      ->will($this->returnValueMap($definitions_map));
+      ->will($this->returnCallback(function ($entity_type_id, $exception_on_invalid = FALSE) use ($definitions) {
+        if (isset($definitions[$entity_type_id])) {
+          return $definitions[$entity_type_id];
+        }
+        elseif (!$exception_on_invalid) {
+          return NULL;
+        }
+        else throw new UnknownPluginException($entity_type_id);
+      }));
     $this->discovery->expects($this->any())
       ->method('getDefinitions')
       ->will($this->returnValue($definitions));
@@ -195,7 +202,7 @@ public function testGetDefinition($entity_type_id, $expected) {
       'banana' => $entity,
     ));
 
-    $entity_type = $this->entityManager->getDefinition($entity_type_id);
+    $entity_type = $this->entityManager->getDefinition($entity_type_id, FALSE);
     if ($expected) {
       $this->assertInstanceOf('Drupal\Core\Entity\EntityTypeInterface', $entity_type);
     }
diff --git a/core/tests/Drupal/Tests/Core/Plugin/Discovery/HookDiscoveryTest.php b/core/tests/Drupal/Tests/Core/Plugin/Discovery/HookDiscoveryTest.php
index 3a120c8..1bc7e4c 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/Discovery/HookDiscoveryTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/Discovery/HookDiscoveryTest.php
@@ -116,7 +116,7 @@ public function testGetDefinition() {
         )
       ));
 
-    $this->assertNull($this->hookDiscovery->getDefinition('test_non_existant'));
+    $this->assertNull($this->hookDiscovery->getDefinition('test_non_existant', FALSE));
 
     $plugin_definition = $this->hookDiscovery->getDefinition('test_id_1');
     $this->assertEquals($plugin_definition['class'], 'Drupal\plugin_test\Plugin\plugin_test\fruit\Apple');
@@ -131,6 +131,21 @@ public function testGetDefinition() {
     $this->assertEquals($plugin_definition['module'], 'hook_discovery_test2');
   }
 
+  /**
+   * Tests the getDefinition method with an unknown plugin ID.
+   *
+   * @see \Drupal\Core\Plugin\Discovery::getDefinition()
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\UnknownPluginException
+   */
+  public function testGetDefinitionWithUnknownID() {
+    $this->moduleHandler->expects($this->once())
+      ->method('getImplementations')
+      ->will($this->returnValue(array()));
+
+    $this->hookDiscovery->getDefinition('test_non_existant', TRUE);
+  }
+
 }
 
 }
