diff --git a/core/core.services.yml b/core/core.services.yml
index 589c5f6..1e4f5d3 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -152,6 +152,12 @@ services:
       - { name: cache.bin, default_backend: cache.backend.chainedfast }
     factory: cache_factory:get
     arguments: [config]
+  cache.config_entity_storage:
+    class: Drupal\Core\Cache\CacheBackendInterface
+    tags:
+      - { name: cache.bin, default_backend: cache.backend.chainedfast }
+    factory: cache_factory:get
+    arguments: [config_entity_storage]
   cache.default:
     class: Drupal\Core\Cache\CacheBackendInterface
     tags:
diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index 262fd0c..cc703cd 100644
--- a/core/lib/Drupal/Core/Block/BlockBase.php
+++ b/core/lib/Drupal/Core/Block/BlockBase.php
@@ -108,6 +108,7 @@ public function defaultConfiguration() {
    */
   public function setConfigurationValue($key, $value) {
     $this->configuration[$key] = $value;
+    return $this;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Block/BlockPluginInterface.php b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
index 88b11a6..9431e30 100644
--- a/core/lib/Drupal/Core/Block/BlockPluginInterface.php
+++ b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
@@ -78,6 +78,8 @@ public function build();
    * @param mixed $value
    *   The value to set for the provided key.
    *
+   * @return $this
+   *
    * @todo This doesn't belong here. Move this into a new base class in
    *   https://www.drupal.org/node/1764380.
    * @todo This does not set a value in \Drupal::config(), so the name is confusing.
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
index 4802173..b11693b 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
@@ -7,7 +7,9 @@
 
 namespace Drupal\Core\Config\Entity;
 
+use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\ConfigImporterException;
 use Drupal\Core\Entity\EntityInterface;
@@ -82,6 +84,13 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
   protected $languageManager;
 
   /**
+   * The config_entity_query cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBackend;
+
+  /**
    * Static cache of entities, keyed first by entity ID, then by an extra key.
    *
    * The additional cache key is to maintain separate caches for different
@@ -111,12 +120,13 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
    *   The language manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) {
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend) {
     parent::__construct($entity_type);
 
     $this->configFactory = $config_factory;
     $this->uuidService = $uuid_service;
     $this->languageManager = $language_manager;
+    $this->cacheBackend = $cache_backend;
   }
 
   /**
@@ -127,7 +137,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $entity_type,
       $container->get('config.factory'),
       $container->get('uuid'),
-      $container->get('language_manager')
+      $container->get('language_manager'),
+      $container->get('cache.config_entity_storage')
     );
   }
 
@@ -455,4 +466,21 @@ public function loadMultipleOverrideFree(array $ids = NULL) {
     return $entities;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function cachedLoadByProperties(array $values = array()) {
+    $cid = $this->entityTypeId . Crypt::hashBase64(serialize($values));
+    if ($cached = $this->cacheBackend->get($cid)) {
+      $result = $cached->data;
+    }
+    else {
+      $result = $this->loadByProperties($values);
+      // Add the config entity list cache tag, so that this is invalidated
+      // when config entities change.
+      $this->cacheBackend->set($cid, $result, CacheBackendInterface::CACHE_PERMANENT, $this->entityType->getListCacheTags());
+    }
+    return $result;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorageInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorageInterface.php
index 8bb9e43..9e4bac4 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorageInterface.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorageInterface.php
@@ -88,4 +88,33 @@ public function loadOverrideFree($id);
    */
   public function loadMultipleOverrideFree(array $ids = NULL);
 
+  /**
+   * Load entities by their property values from cache, if available.
+   *
+   * If there is no cache entry available the method falls back to
+   * self::loadByProperties().
+   *
+   * Querying configuration entities is expensive. If config entities need to be
+   * queried by property during regular run-time (for example, on every non
+   * cached page request) then this method is preferred over
+   * self::loadByProperties(), especially if the $values array is not highly
+   * dynamic. If $values is highly dynamic consider using config entity lookup
+   * keys.
+   *
+   * Over-use of this method is discouraged since, by default, it stores entries
+   * in APC.
+   *
+   * @param array $values
+   *   An associative array where the keys are the property names and the
+   *   values are the values those properties must have.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface[]
+   *   An array of entity objects indexed by their ids.
+   *
+   * @see \Drupal\Core\Config\Entity\ConfigEntityStorageInterface::loadByProperties()
+   * @see \Drupal\Core\Config\Entity\ConfigEntityType::$lookup_keys
+   * @see \Drupal\block\BlockRepository::getVisibleBlocksPerRegion()
+   */
+  public function cachedLoadByProperties(array $values = array());
+
 }
diff --git a/core/lib/Drupal/Core/Field/BaseFieldOverrideStorage.php b/core/lib/Drupal/Core/Field/BaseFieldOverrideStorage.php
index 0b559ba..ebdba47 100644
--- a/core/lib/Drupal/Core/Field/BaseFieldOverrideStorage.php
+++ b/core/lib/Drupal/Core/Field/BaseFieldOverrideStorage.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Field;
 
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -32,8 +33,8 @@ class BaseFieldOverrideStorage extends FieldConfigStorageBase {
    * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
    *   The field type plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, FieldTypePluginManagerInterface $field_type_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend, FieldTypePluginManagerInterface $field_type_manager) {
+    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $cache_backend);
     $this->fieldTypeManager = $field_type_manager;
   }
 
@@ -46,6 +47,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('config.factory'),
       $container->get('uuid'),
       $container->get('language_manager'),
+      $container->get('cache.config_entity_storage'),
       $container->get('plugin.manager.field.field_type')
     );
   }
diff --git a/core/modules/block/src/BlockRepository.php b/core/modules/block/src/BlockRepository.php
index 980e0ad..bea8478 100644
--- a/core/modules/block/src/BlockRepository.php
+++ b/core/modules/block/src/BlockRepository.php
@@ -19,7 +19,7 @@ class BlockRepository implements BlockRepositoryInterface {
   /**
    * The block storage.
    *
-   * @var \Drupal\Core\Entity\EntityStorageInterface
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
    */
   protected $blockStorage;
 
@@ -55,7 +55,7 @@ public function getVisibleBlocksPerRegion(array $contexts) {
     $empty = array_fill_keys($active_theme->getRegions(), array());
 
     $full = array();
-    foreach ($this->blockStorage->loadByProperties(array('theme' => $active_theme->getName())) as $block_id => $block) {
+    foreach ($this->blockStorage->cachedLoadByProperties(array('theme' => $active_theme->getName())) as $block_id => $block) {
       /** @var \Drupal\block\BlockInterface $block */
       // Set the contexts on the block before checking access.
       if ($block->setContexts($contexts)->access('view')) {
diff --git a/core/modules/block/src/Tests/BlockSystemBrandingTest.php b/core/modules/block/src/Tests/BlockSystemBrandingTest.php
index 57ebc85..badfc42 100644
--- a/core/modules/block/src/Tests/BlockSystemBrandingTest.php
+++ b/core/modules/block/src/Tests/BlockSystemBrandingTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\block\Tests;
 
+use Drupal\block\Entity\Block;
+
 /**
  * Tests branding block display.
  *
@@ -54,9 +56,11 @@ public function testSystemBrandingSettings() {
     $this->assertCacheTag('config:system.site');
 
     // Turn just the logo off.
-    $this->config('block.block.site-branding')
-      ->set('settings.use_site_logo', 0)
-      ->save();
+    /** @var \Drupal\block\BlockInterface $block */
+    $block = Block::load('site-branding');
+    $block->getPlugin()->setConfigurationValue('use_site_logo', FALSE);
+    $block->save();
+
     $this->drupalGet('');
     $site_logo_element = $this->xpath($site_logo_xpath);
     $site_name_element = $this->xpath($site_name_xpath);
@@ -68,10 +72,11 @@ public function testSystemBrandingSettings() {
     $this->assertCacheTag('config:system.site');
 
     // Turn just the site name off.
-    $this->config('block.block.site-branding')
-      ->set('settings.use_site_logo', 1)
-      ->set('settings.use_site_name', 0)
-      ->save();
+    $block->getPlugin()
+      ->setConfigurationValue('use_site_logo', TRUE)
+      ->setConfigurationValue('use_site_name', FALSE);
+    $block->save();
+
     $this->drupalGet('');
     $site_logo_element = $this->xpath($site_logo_xpath);
     $site_name_element = $this->xpath($site_name_xpath);
@@ -83,10 +88,11 @@ public function testSystemBrandingSettings() {
     $this->assertCacheTag('config:system.site');
 
     // Turn just the site slogan off.
-    $this->config('block.block.site-branding')
-      ->set('settings.use_site_name', 1)
-      ->set('settings.use_site_slogan', 0)
-      ->save();
+    $block->getPlugin()
+      ->setConfigurationValue('use_site_name', TRUE)
+      ->setConfigurationValue('use_site_slogan', FALSE);
+    $block->save();
+
     $this->drupalGet('');
     $site_logo_element = $this->xpath($site_logo_xpath);
     $site_name_element = $this->xpath($site_name_xpath);
@@ -98,10 +104,11 @@ public function testSystemBrandingSettings() {
     $this->assertCacheTag('config:system.site');
 
     // Turn the site name and the site slogan off.
-    $this->config('block.block.site-branding')
-      ->set('settings.use_site_name', 0)
-      ->set('settings.use_site_slogan', 0)
-      ->save();
+    $block->getPlugin()
+      ->setConfigurationValue('use_site_name', FALSE)
+      ->setConfigurationValue('use_site_slogan', FALSE);
+    $block->save();
+
     $this->drupalGet('');
     $site_logo_element = $this->xpath($site_logo_xpath);
     $site_name_element = $this->xpath($site_name_xpath);
diff --git a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
index 56b90ca..586d473 100644
--- a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
+++ b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php
@@ -24,7 +24,7 @@ class BlockRepositoryTest extends UnitTestCase {
   protected $blockRepository;
 
   /**
-   * @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
    */
   protected $blockStorage;
 
@@ -64,7 +64,7 @@ protected function setUp() {
       ->will($this->returnValue($active_theme));
 
     $this->contextHandler = $this->getMock('Drupal\Core\Plugin\Context\ContextHandlerInterface');
-    $this->blockStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
+    $this->blockStorage = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityStorageInterface');
     $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
     $entity_manager->expects($this->any())
       ->method('getStorage')
@@ -97,7 +97,7 @@ public function testGetVisibleBlocksPerRegion(array $blocks_config, array $expec
     }
 
     $this->blockStorage->expects($this->once())
-      ->method('loadByProperties')
+      ->method('cachedLoadByProperties')
       ->with(['theme' => $this->theme])
       ->willReturn($blocks);
     $result = [];
@@ -159,7 +159,7 @@ public function testGetVisibleBlocksPerRegionWithContext() {
 
     $contexts = [];
     $this->blockStorage->expects($this->once())
-      ->method('loadByProperties')
+      ->method('cachedLoadByProperties')
       ->with(['theme' => $this->theme])
       ->willReturn($blocks);
     $result = [];
diff --git a/core/modules/field/src/FieldConfigStorage.php b/core/modules/field/src/FieldConfigStorage.php
index bb6a257..62859d3 100644
--- a/core/modules/field/src/FieldConfigStorage.php
+++ b/core/modules/field/src/FieldConfigStorage.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field;
 
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
@@ -62,8 +63,8 @@ class FieldConfigStorage extends FieldConfigStorageBase {
    * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
    *   The field type plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend, EntityManagerInterface $entity_manager, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
+    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $cache_backend);
     $this->entityManager = $entity_manager;
     $this->state = $state;
     $this->fieldTypeManager = $field_type_manager;
@@ -78,6 +79,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('config.factory'),
       $container->get('uuid'),
       $container->get('language_manager'),
+      $container->get('cache.config_entity_storage'),
       $container->get('entity.manager'),
       $container->get('state'),
       $container->get('plugin.manager.field.field_type')
diff --git a/core/modules/field/src/FieldStorageConfigStorage.php b/core/modules/field/src/FieldStorageConfigStorage.php
index 4e7a280..f79097b 100644
--- a/core/modules/field/src/FieldStorageConfigStorage.php
+++ b/core/modules/field/src/FieldStorageConfigStorage.php
@@ -8,6 +8,7 @@
 namespace Drupal\field;
 
 use Drupal\Component\Uuid\UuidInterface;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\Entity\ConfigEntityStorage;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -72,8 +73,8 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
    * @param \Drupal\Component\Plugin\PluginManagerInterface\FieldTypePluginManagerInterface
    *   The field type plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
+    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $cache_backend);
     $this->entityManager = $entity_manager;
     $this->moduleHandler = $module_handler;
     $this->state = $state;
@@ -89,6 +90,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('config.factory'),
       $container->get('uuid'),
       $container->get('language_manager'),
+      $container->get('cache.config_entity_storage'),
       $container->get('entity.manager'),
       $container->get('module_handler'),
       $container->get('state'),
diff --git a/core/modules/migrate_drupal/src/MigrationStorage.php b/core/modules/migrate_drupal/src/MigrationStorage.php
index eb0349b..c1d3815 100644
--- a/core/modules/migrate_drupal/src/MigrationStorage.php
+++ b/core/modules/migrate_drupal/src/MigrationStorage.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Uuid\UuidInterface;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageException;
@@ -51,8 +52,8 @@ class MigrationStorage extends BaseMigrationStorage {
    * @param \Drupal\migrate_drupal\Plugin\MigratePluginManager
    *  The cckfield plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, MigratePluginManager $cck_plugin_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
+  public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend, MigratePluginManager $cck_plugin_manager) {
+    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $cache_backend);
     $this->cckPluginManager = $cck_plugin_manager;
   }
 
@@ -65,6 +66,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('config.factory'),
       $container->get('uuid'),
       $container->get('language_manager'),
+      $container->get('cache.config_entity_storage'),
       $container->get('plugin.manager.migrate.cckfield')
     );
   }
diff --git a/core/modules/shortcut/src/ShortcutSetStorage.php b/core/modules/shortcut/src/ShortcutSetStorage.php
index f575856..00693ea 100644
--- a/core/modules/shortcut/src/ShortcutSetStorage.php
+++ b/core/modules/shortcut/src/ShortcutSetStorage.php
@@ -8,6 +8,7 @@
 namespace Drupal\shortcut;
 
 use Drupal\Component\Uuid\UuidInterface;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\Entity\ConfigEntityStorage;
 use Drupal\Core\Entity\EntityTypeInterface;
@@ -44,8 +45,8 @@ class ShortcutSetStorage extends ConfigEntityStorage implements ShortcutSetStora
    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
    *   The language manager.
    */
-  public function __construct(EntityTypeInterface $entity_info, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager) {
-    parent::__construct($entity_info, $config_factory, $uuid_service, $language_manager);
+  public function __construct(EntityTypeInterface $entity_info, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager, CacheBackendInterface $cache_backend) {
+    parent::__construct($entity_info, $config_factory, $uuid_service, $language_manager, $cache_backend);
 
     $this->moduleHandler = $module_handler;
   }
@@ -59,7 +60,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('config.factory'),
       $container->get('uuid'),
       $container->get('module_handler'),
-      $container->get('language_manager')
+      $container->get('language_manager'),
+      $container->get('cache.config_entity_storage')
     );
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index c4413eb..c11a9a5 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Config\Entity {
 
+use Drupal\Core\Cache\MemoryBackend;
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Language\Language;
@@ -104,6 +105,13 @@ class ConfigEntityStorageTest extends UnitTestCase {
   protected $configManager;
 
   /**
+   * The config_entity_query cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheBackend;
+
+  /**
    * {@inheritdoc}
    *
    * @covers ::__construct
@@ -146,9 +154,11 @@ protected function setUp() {
 
     $this->entityQuery = $this->getMock('Drupal\Core\Entity\Query\QueryInterface');
 
+    $this->cacheBackend = new MemoryBackend('config_entity_storage');
+
     $this->entityStorage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
-      ->setConstructorArgs(array($this->entityType, $this->configFactory, $this->uuidService, $this->languageManager))
-      ->setMethods(array('getQuery'))
+      ->setConstructorArgs(array($this->entityType, $this->configFactory, $this->uuidService, $this->languageManager, $this->cacheBackend))
+      ->setMethods(array('getQuery', 'loadByProperties'))
       ->getMock();
     $this->entityStorage->expects($this->any())
       ->method('getQuery')
@@ -856,6 +866,34 @@ public function testDeleteNothing() {
   }
 
   /**
+   * @covers ::cachedLoadByProperties
+   */
+  public function testCachedLoadByProperties() {
+
+    $values = ['test' => 'blah'];
+    $result = [
+      'foo' => $this->getMockEntity(['id' => 'foo', 'test' => 'blah'])
+    ];
+
+    // Ensure that we only call the storage's loadByProperties() method twice.
+    $this->entityStorage->expects($this->exactly(2))
+      ->method('loadByProperties')
+      ->with($values)
+      ->willReturn($result);
+
+    // This to cachedLoadByProperties() will fall through to loadByProperties().
+    $this->assertEquals($result, $this->entityStorage->cachedLoadByProperties($values));
+    // This call to cachedLoadByProperties() should use the cache.
+    $this->assertEquals($result, $this->entityStorage->cachedLoadByProperties($values));
+
+    $this->cacheBackend->invalidateTags($this->entityType->getListCacheTags());
+    // This to cachedLoadByProperties() will fall through to loadByProperties().
+    $this->assertEquals($result, $this->entityStorage->cachedLoadByProperties($values));
+    // This call to cachedLoadByProperties() should use the cache.
+    $this->assertEquals($result, $this->entityStorage->cachedLoadByProperties($values));
+  }
+
+  /**
    * Creates an entity with specific methods mocked.
    *
    * @param array $values
