diff --git a/core/lib/Drupal/Core/Access/AccessResult.php b/core/lib/Drupal/Core/Access/AccessResult.php
index cd2b958..72edf4e 100644
--- a/core/lib/Drupal/Core/Access/AccessResult.php
+++ b/core/lib/Drupal/Core/Access/AccessResult.php
@@ -8,6 +8,8 @@
 
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
+use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
 use Drupal\Core\Config\ConfigBase;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -25,47 +27,10 @@
  *
  * When using ::orIf() and ::andIf(), cacheability metadata will be merged
  * accordingly as well.
- *
- * @todo Use RefinableCacheableDependencyInterface and the corresponding trait in
- *   https://www.drupal.org/node/2526326.
  */
-abstract class AccessResult implements AccessResultInterface, CacheableDependencyInterface {
-
-  /**
-   * The cache context IDs (to vary a cache item ID based on active contexts).
-   *
-   * @see \Drupal\Core\Cache\Context\CacheContextInterface
-   * @see \Drupal\Core\Cache\Context\CacheContextsManager::convertTokensToKeys()
-   *
-   * @var string[]
-   */
-  protected $contexts;
-
-  /**
-   * The cache tags.
-   *
-   * @var array
-   */
-  protected $tags;
+abstract class AccessResult implements AccessResultInterface, RefinableCacheableDependencyInterface {
 
-  /**
-   * The maximum caching time in seconds.
-   *
-   * @var int
-   */
-  protected $maxAge;
-
-  /**
-   * Constructs a new AccessResult object.
-   */
-  public function __construct() {
-    $this->resetCacheContexts()
-      ->resetCacheTags()
-      // Max-age must be non-zero for an access result to be cacheable.
-      // Typically, cache items are invalidated via associated cache tags, not
-      // via a maximum age.
-      ->setCacheMaxAge(Cache::PERMANENT);
-  }
+  use RefinableCacheableDependencyTrait;
 
   /**
    * Creates an AccessResultInterface object with isNeutral() === TRUE.
@@ -215,35 +180,22 @@ public function isNeutral() {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    sort($this->contexts);
-    return $this->contexts;
+    sort($this->cacheContexts);
+    return $this->cacheContexts;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getCacheTags() {
-    return $this->tags;
+    return $this->cacheTags;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getCacheMaxAge() {
-    return $this->maxAge;
-  }
-
-  /**
-   * Adds cache contexts associated with the access result.
-   *
-   * @param string[] $contexts
-   *   An array of cache context IDs, used to generate a cache ID.
-   *
-   * @return $this
-   */
-  public function addCacheContexts(array $contexts) {
-    $this->contexts = array_unique(array_merge($this->contexts, $contexts));
-    return $this;
+    return $this->cacheMaxAge;
   }
 
   /**
@@ -252,20 +204,7 @@ public function addCacheContexts(array $contexts) {
    * @return $this
    */
   public function resetCacheContexts() {
-    $this->contexts = array();
-    return $this;
-  }
-
-  /**
-   * Adds cache tags associated with the access result.
-   *
-   * @param array $tags
-   *   An array of cache tags.
-   *
-   * @return $this
-   */
-  public function addCacheTags(array $tags) {
-    $this->tags = Cache::mergeTags($this->tags, $tags);
+    $this->cacheContexts = array();
     return $this;
   }
 
@@ -275,7 +214,7 @@ public function addCacheTags(array $tags) {
    * @return $this
    */
   public function resetCacheTags() {
-    $this->tags = array();
+    $this->cacheTags = array();
     return $this;
   }
 
@@ -288,7 +227,7 @@ public function resetCacheTags() {
    * @return $this
    */
   public function setCacheMaxAge($max_age) {
-    $this->maxAge = $max_age;
+    $this->cacheMaxAge = $max_age;
     return $this;
   }
 
@@ -321,8 +260,7 @@ public function cachePerUser() {
    * @return $this
    */
   public function cacheUntilEntityChanges(EntityInterface $entity) {
-    $this->addCacheTags($entity->getCacheTags());
-    return $this;
+    return $this->addCacheableDependency($entity);
   }
 
   /**
@@ -334,8 +272,7 @@ public function cacheUntilEntityChanges(EntityInterface $entity) {
    * @return $this
    */
   public function cacheUntilConfigurationChanges(ConfigBase $configuration) {
-    $this->addCacheTags($configuration->getCacheTags());
-    return $this;
+    return $this->addCacheableDependency($configuration);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Cache/CacheableMetadata.php b/core/lib/Drupal/Core/Cache/CacheableMetadata.php
index 33d5afb..33429bf 100644
--- a/core/lib/Drupal/Core/Cache/CacheableMetadata.php
+++ b/core/lib/Drupal/Core/Cache/CacheableMetadata.php
@@ -11,50 +11,16 @@
  *
  * @ingroup cache
  *
- * @todo Use RefinableCacheableDependencyInterface and the corresponding trait in
- *   https://www.drupal.org/node/2526326.
  */
-class CacheableMetadata implements CacheableDependencyInterface {
+class CacheableMetadata implements RefinableCacheableDependencyInterface {
 
-  /**
-   * Cache contexts.
-   *
-   * @var string[]
-   */
-  protected $contexts = [];
-
-  /**
-   * Cache tags.
-   *
-   * @var string[]
-   */
-  protected $tags = [];
-
-  /**
-   * Cache max-age.
-   *
-   * @var int
-   */
-  protected $maxAge = Cache::PERMANENT;
+  use RefinableCacheableDependencyTrait;
 
   /**
    * {@inheritdoc}
    */
   public function getCacheTags() {
-    return $this->tags;
-  }
-
-  /**
-   * Adds cache tags.
-   *
-   * @param string[] $cache_tags
-   *   The cache tags to be added.
-   *
-   * @return $this
-   */
-  public function addCacheTags(array $cache_tags) {
-    $this->tags = Cache::mergeTags($this->tags, $cache_tags);
-    return $this;
+    return $this->cacheTags;
   }
 
   /**
@@ -66,7 +32,7 @@ public function addCacheTags(array $cache_tags) {
    * @return $this
    */
   public function setCacheTags(array $cache_tags) {
-    $this->tags = $cache_tags;
+    $this->cacheTags = $cache_tags;
     return $this;
   }
 
@@ -74,20 +40,7 @@ public function setCacheTags(array $cache_tags) {
    * {@inheritdoc}
    */
   public function getCacheContexts() {
-    return $this->contexts;
-  }
-
-  /**
-   * Adds cache contexts.
-   *
-   * @param string[] $cache_contexts
-   *   The cache contexts to be added.
-   *
-   * @return $this
-   */
-  public function addCacheContexts(array $cache_contexts) {
-    $this->contexts = Cache::mergeContexts($this->contexts, $cache_contexts);
-    return $this;
+    return $this->cacheContexts;
   }
 
   /**
@@ -99,7 +52,7 @@ public function addCacheContexts(array $cache_contexts) {
    * @return $this
    */
   public function setCacheContexts(array $cache_contexts) {
-    $this->contexts = $cache_contexts;
+    $this->cacheContexts = $cache_contexts;
     return $this;
   }
 
@@ -107,7 +60,7 @@ public function setCacheContexts(array $cache_contexts) {
    * {@inheritdoc}
    */
   public function getCacheMaxAge() {
-    return $this->maxAge;
+    return $this->cacheMaxAge;
   }
 
   /**
@@ -128,36 +81,7 @@ public function setCacheMaxAge($max_age) {
       throw new \InvalidArgumentException('$max_age must be an integer');
     }
 
-    $this->maxAge = $max_age;
-    return $this;
-  }
-
-  /**
-   * Adds a dependency on an object: merges its cacheability metadata.
-   *
-   * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $other_object
-   *   The dependency. If the object implements CacheableDependencyInterface,
-   *   then its cacheability metadata will be used. Otherwise, the passed in
-   *   object must be assumed to be uncacheable, so max-age 0 is set.
-   *
-   * @return $this
-   */
-  public function addCacheableDependency($other_object) {
-    if ($other_object instanceof CacheableDependencyInterface) {
-      $this->addCacheTags($other_object->getCacheTags());
-      $this->addCacheContexts($other_object->getCacheContexts());
-      if ($this->maxAge === Cache::PERMANENT) {
-        $this->maxAge = $other_object->getCacheMaxAge();
-      }
-      elseif (($max_age = $other_object->getCacheMaxAge()) && $max_age !== Cache::PERMANENT) {
-        $this->maxAge = Cache::mergeMaxAges($this->maxAge, $max_age);
-      }
-    }
-    else {
-      // Not a cacheable dependency, this can not be cached.
-      $this->maxAge = 0;
-    }
-
+    $this->cacheMaxAge = $max_age;
     return $this;
   }
 
@@ -175,34 +99,34 @@ public function merge(CacheableMetadata $other) {
 
     // This is called many times per request, so avoid merging unless absolutely
     // necessary.
-    if (empty($this->contexts)) {
-      $result->contexts = $other->contexts;
+    if (empty($this->cacheContexts)) {
+      $result->cacheContexts = $other->cacheContexts;
     }
-    elseif (empty($other->contexts)) {
-      $result->contexts = $this->contexts;
+    elseif (empty($other->cacheContexts)) {
+      $result->cacheContexts = $this->cacheContexts;
     }
     else {
-      $result->contexts = Cache::mergeContexts($this->contexts, $other->contexts);
+      $result->cacheContexts = Cache::mergeContexts($this->cacheContexts, $other->cacheContexts);
     }
 
-    if (empty($this->tags)) {
-      $result->tags = $other->tags;
+    if (empty($this->cacheTags)) {
+      $result->cacheTags = $other->cacheTags;
     }
-    elseif (empty($other->tags)) {
-      $result->tags = $this->tags;
+    elseif (empty($other->cacheTags)) {
+      $result->cacheTags = $this->cacheTags;
     }
     else {
-      $result->tags = Cache::mergeTags($this->tags, $other->tags);
+      $result->cacheTags = Cache::mergeTags($this->cacheTags, $other->cacheTags);
     }
 
-    if ($this->maxAge === Cache::PERMANENT) {
-      $result->maxAge = $other->maxAge;
+    if ($this->cacheMaxAge === Cache::PERMANENT) {
+      $result->cacheMaxAge = $other->cacheMaxAge;
     }
-    elseif ($other->maxAge === Cache::PERMANENT) {
-      $result->maxAge = $this->maxAge;
+    elseif ($other->cacheMaxAge === Cache::PERMANENT) {
+      $result->cacheMaxAge = $this->cacheMaxAge;
     }
     else {
-      $result->maxAge = Cache::mergeMaxAges($this->maxAge, $other->maxAge);
+      $result->cacheMaxAge = Cache::mergeMaxAges($this->cacheMaxAge, $other->cacheMaxAge);
     }
     return $result;
   }
@@ -214,9 +138,9 @@ public function merge(CacheableMetadata $other) {
    *   A render array.
    */
   public function applyTo(array &$build) {
-    $build['#cache']['contexts'] = $this->contexts;
-    $build['#cache']['tags'] = $this->tags;
-    $build['#cache']['max-age'] = $this->maxAge;
+    $build['#cache']['contexts'] = $this->cacheContexts;
+    $build['#cache']['tags'] = $this->cacheTags;
+    $build['#cache']['max-age'] = $this->cacheMaxAge;
   }
 
   /**
@@ -229,9 +153,9 @@ public function applyTo(array &$build) {
    */
   public static function createFromRenderArray(array $build) {
     $meta = new static();
-    $meta->contexts = (isset($build['#cache']['contexts'])) ? $build['#cache']['contexts'] : [];
-    $meta->tags = (isset($build['#cache']['tags'])) ? $build['#cache']['tags'] : [];
-    $meta->maxAge = (isset($build['#cache']['max-age'])) ? $build['#cache']['max-age'] : Cache::PERMANENT;
+    $meta->cacheContexts = (isset($build['#cache']['contexts'])) ? $build['#cache']['contexts'] : [];
+    $meta->cacheTags = (isset($build['#cache']['tags'])) ? $build['#cache']['tags'] : [];
+    $meta->cacheMaxAge = (isset($build['#cache']['max-age'])) ? $build['#cache']['max-age'] : Cache::PERMANENT;
     return $meta;
   }
 
@@ -249,16 +173,16 @@ public static function createFromRenderArray(array $build) {
   public static function createFromObject($object) {
     if ($object instanceof CacheableDependencyInterface) {
       $meta = new static();
-      $meta->contexts = $object->getCacheContexts();
-      $meta->tags = $object->getCacheTags();
-      $meta->maxAge = $object->getCacheMaxAge();
+      $meta->cacheContexts = $object->getCacheContexts();
+      $meta->cacheTags = $object->getCacheTags();
+      $meta->cacheMaxAge = $object->getCacheMaxAge();
       return $meta;
     }
 
     // Objects that don't implement CacheableDependencyInterface must be assumed
     // to be uncacheable, so set max-age 0.
     $meta = new static();
-    $meta->maxAge = 0;
+    $meta->cacheMaxAge = 0;
     return $meta;
   }
 
diff --git a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php
index ff9c172..9ba1ba1 100644
--- a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php
+++ b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php
@@ -52,4 +52,16 @@ public function addCacheTags(array $cache_tags);
    */
   public function mergeCacheMaxAge($max_age);
 
+  /**
+   * Adds a dependency on an object: merges its cacheability metadata.
+   *
+   * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $other_object
+   *   The dependency. If the object implements CacheableDependencyInterface,
+   *   then its cacheability metadata will be used. Otherwise, the passed in
+   *   object must be assumed to be uncacheable, so max-age 0 is set.
+   *
+   * @return $this
+   */
+  public function addCacheableDependency($other_object);
+
 }
diff --git a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php
index 972a829..7a5041f 100644
--- a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php
+++ b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php
@@ -37,7 +37,9 @@
    * {@inheritdoc}
    */
   public function addCacheContexts(array $cache_contexts) {
-    $this->cacheContexts = Cache::mergeContexts($this->cacheContexts, $cache_contexts);
+    if ($cache_contexts) {
+      $this->cacheContexts = Cache::mergeContexts($this->cacheContexts, $cache_contexts);
+    }
     return $this;
   }
 
@@ -45,7 +47,9 @@ public function addCacheContexts(array $cache_contexts) {
    * {@inheritdoc}
    */
   public function addCacheTags(array $cache_tags) {
-    $this->cacheTags = Cache::mergeTags($this->cacheTags, $cache_tags);
+    if ($cache_tags) {
+      $this->cacheTags = Cache::mergeTags($this->cacheTags, $cache_tags);
+    }
     return $this;
   }
 
@@ -53,7 +57,29 @@ public function addCacheTags(array $cache_tags) {
    * {@inheritdoc}
    */
   public function mergeCacheMaxAge($max_age) {
-    $this->cacheMaxAge = Cache::mergeMaxAges($this->cacheMaxAge, $max_age);
+    if ($this->cacheMaxAge === Cache::PERMANENT) {
+      $this->cacheMaxAge = $max_age;
+    }
+    elseif ($max_age && $max_age !== Cache::PERMANENT) {
+      $this->cacheMaxAge = Cache::mergeMaxAges($this->cacheMaxAge, $max_age);
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addCacheableDependency($other_object) {
+    if ($other_object instanceof CacheableDependencyInterface) {
+      $this->addCacheTags($other_object->getCacheTags());
+      $this->addCacheContexts($other_object->getCacheContexts());
+      $this->mergeCacheMaxAge($other_object->getCacheMaxAge());
+    }
+    else {
+      // Not a cacheable dependency, this can not be cached.
+      $this->cacheMaxAge = 0;
+    }
+
     return $this;
   }
 
diff --git a/core/modules/content_translation/tests/src/Unit/Access/ContentTranslationManageAccessCheckTest.php b/core/modules/content_translation/tests/src/Unit/Access/ContentTranslationManageAccessCheckTest.php
index 512e735..f1df085 100644
--- a/core/modules/content_translation/tests/src/Unit/Access/ContentTranslationManageAccessCheckTest.php
+++ b/core/modules/content_translation/tests/src/Unit/Access/ContentTranslationManageAccessCheckTest.php
@@ -9,6 +9,8 @@
 
 use Drupal\content_translation\Access\ContentTranslationManageAccessCheck;
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\Core\Language\Language;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\Routing\Route;
@@ -28,6 +30,14 @@ class ContentTranslationManageAccessCheckTest extends UnitTestCase {
    * @covers ::access
    */
   public function testCreateAccess() {
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+
     // Set the mock translation handler.
     $translation_handler = $this->getMock('\Drupal\content_translation\ContentTranslationHandlerInterface');
     $translation_handler->expects($this->once())
@@ -74,6 +84,12 @@ public function testCreateAccess() {
       ->with()
       ->will($this->returnValue(array()));
     $entity->expects($this->once())
+      ->method('getCacheContexts')
+      ->willReturn([]);
+    $entity->expects($this->once())
+      ->method('getCacheMaxAge')
+      ->willReturn(Cache::PERMANENT);
+    $entity->expects($this->once())
       ->method('getCacheTags')
       ->will($this->returnValue(array('node:1337')));
 
diff --git a/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php b/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php
index 6f352ae..5fba2b2 100644
--- a/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php
+++ b/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\quickedit\Unit\Access;
 
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\quickedit\Access\EditEntityFieldAccessCheck;
 use Drupal\Tests\UnitTestCase;
 use Drupal\field\FieldStorageConfigInterface;
@@ -33,6 +34,13 @@ class EditEntityFieldAccessCheckTest extends UnitTestCase {
    */
   protected function setUp() {
     $this->editAccessCheck = new EditEntityFieldAccessCheck();
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
   }
 
   /**
@@ -41,34 +49,11 @@ protected function setUp() {
    * @see \Drupal\Tests\edit\Unit\quickedit\Access\EditEntityFieldAccessCheckTest::testAccess()
    */
   public function providerTestAccess() {
-    $editable_entity = $this->createMockEntity();
-    $editable_entity->expects($this->any())
-      ->method('access')
-      ->will($this->returnValue(AccessResult::allowed()->cachePerPermissions()));
-
-    $non_editable_entity = $this->createMockEntity();
-    $non_editable_entity->expects($this->any())
-      ->method('access')
-      ->will($this->returnValue(AccessResult::neutral()->cachePerPermissions()));
-
-    $field_storage_with_access = $this->getMockBuilder('Drupal\field\Entity\FieldStorageConfig')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $field_storage_with_access->expects($this->any())
-      ->method('access')
-      ->will($this->returnValue(AccessResult::allowed()));
-    $field_storage_without_access = $this->getMockBuilder('Drupal\field\Entity\FieldStorageConfig')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $field_storage_without_access->expects($this->any())
-      ->method('access')
-      ->will($this->returnValue(AccessResult::neutral()));
-
     $data = array();
-    $data[] = array($editable_entity, $field_storage_with_access, AccessResult::allowed()->cachePerPermissions());
-    $data[] = array($non_editable_entity, $field_storage_with_access, AccessResult::neutral()->cachePerPermissions());
-    $data[] = array($editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerPermissions());
-    $data[] = array($non_editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerPermissions());
+    $data[] = array(TRUE, TRUE, AccessResult::allowed());
+    $data[] = array(FALSE, TRUE, AccessResult::neutral());
+    $data[] = array(TRUE, FALSE, AccessResult::neutral());
+    $data[] = array(FALSE, FALSE, AccessResult::neutral());
 
     return $data;
   }
@@ -76,16 +61,28 @@ public function providerTestAccess() {
   /**
    * Tests the method for checking access to routes.
    *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   A mocked entity.
-   * @param \Drupal\field\FieldStorageConfigInterface $field_storage
-   *   A mocked field storage.
-   * @param bool|null $expected_result
+   * @param bool $entity_is_editable
+   *   Whether the subject entity is editable.
+   * @param bool $field_storage_access
+   *   Whether the user has access to the field storage entity.
+   * @param \Drupal\Core\Access\AccessResult $expected_result
    *   The expected result of the access call.
    *
    * @dataProvider providerTestAccess
    */
-  public function testAccess(EntityInterface $entity, FieldStorageConfigInterface $field_storage = NULL, $expected_result) {
+  public function testAccess($entity_is_editable, $field_storage_access, AccessResult $expected_result) {
+    $entity = $this->createMockEntity();
+    $entity->expects($this->any())
+      ->method('access')
+      ->willReturn(AccessResult::allowedIf($entity_is_editable)->cachePerPermissions());
+
+    $field_storage = $this->getMock('Drupal\field\FieldStorageConfigInterface');
+    $field_storage->expects($this->any())
+      ->method('access')
+      ->willReturn(AccessResult::allowedIf($field_storage_access));
+
+    $expected_result->cachePerPermissions();
+
     $field_name = 'valid';
     $entity_with_field = clone $entity;
     $entity_with_field->expects($this->any())
diff --git a/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php b/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
index 34f7590..a9d2597 100644
--- a/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
+++ b/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\Tests\UnitTestCase;
 use Drupal\user\UserAccessControlHandler;
 
@@ -62,6 +63,14 @@ class UserAccessControlHandlerTest extends UnitTestCase {
    */
   public function setUp() {
     parent::setUp();
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+
     $this->viewer = $this->getMock('\Drupal\Core\Session\AccountInterface');
     $this->viewer
       ->expects($this->any())
diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php
index 792898a..00b8b14 100644
--- a/core/modules/views_ui/src/ViewUI.php
+++ b/core/modules/views_ui/src/ViewUI.php
@@ -1364,4 +1364,11 @@ public function addCacheTags(array $cache_tags) {
     return $this->storage->addCacheTags($cache_tags);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function addCacheableDependency($other_object) {
+    return $this->storage->addCacheableDependency($other_object);
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
index 128f2d4..cb77e78 100644
--- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
@@ -95,6 +95,14 @@ protected function setUp() {
 
     $this->container = new ContainerBuilder();
 
+
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($this->container);
+
     $this->routeCollection = new RouteCollection();
     $this->routeCollection->add('test_route_1', new Route('/test-route-1'));
     $this->routeCollection->add('test_route_2', new Route('/test-route-2', array(), array('_access' => 'TRUE')));
diff --git a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php
index 123888a..3ffebd7 100644
--- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Access\AccessResultNeutral;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -20,6 +21,19 @@
  */
 class AccessResultTest extends UnitTestCase {
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+  }
+
   protected function assertDefaultCacheability(AccessResult $access) {
     $this->assertSame([], $access->getCacheContexts());
     $this->assertSame([], $access->getCacheTags());
@@ -29,7 +43,6 @@ protected function assertDefaultCacheability(AccessResult $access) {
   /**
    * Tests the construction of an AccessResult object.
    *
-   * @covers ::__construct
    * @covers ::neutral
    */
   public function testConstruction() {
@@ -423,9 +436,15 @@ public function testCacheTags() {
     // ::cacheUntilEntityChanges() convenience method.
     $node = $this->getMock('\Drupal\node\NodeInterface');
     $node->expects($this->any())
+      ->method('getCacheContexts')
+      ->willReturn([]);
+    $node->expects($this->any())
+      ->method('getCacheMaxAge')
+      ->willReturn(Cache::PERMANENT);
+    $tags = array('node:20011988');
+    $node->expects($this->any())
       ->method('getCacheTags')
       ->will($this->returnValue(array('node:20011988')));
-    $tags = array('node:20011988');
     $a = AccessResult::neutral()->addCacheTags($tags);
     $verify($a, $tags);
     $b = AccessResult::neutral()->cacheUntilEntityChanges($node);
@@ -435,6 +454,12 @@ public function testCacheTags() {
     // ::cacheUntilConfigurationChanges() convenience method.
     $configuration = $this->getMock('\Drupal\Core\Config\ConfigBase');
     $configuration->expects($this->any())
+      ->method('getCacheContexts')
+      ->willReturn([]);
+    $configuration->expects($this->any())
+      ->method('getCacheMaxAge')
+      ->willReturn(Cache::PERMANENT);
+    $configuration->expects($this->any())
       ->method('getCacheTags')
       ->will($this->returnValue(array('config:foo.bar.baz')));
     $tags = array('config:foo.bar.baz');
@@ -833,8 +858,16 @@ public function testOrIfCacheabilityMerging() {
    * @covers ::allowedIfHasPermissions
    *
    * @dataProvider providerTestAllowedIfHasPermissions
+   *
+   * @param string[] $permissions
+   *   The permissions to check for.
+   * @param string $conjunction
+   *   The conjunction to use when checking for permission. Either 'AND" or
+   *   'OR'.
+   * @param \Drupal\Core\Access\AccessResult $expected_access
+   *   The expected access check result.
    */
-  public function testAllowedIfHasPermissions($permissions, $conjunction, $expected_access) {
+  public function testAllowedIfHasPermissions($permissions, $conjunction, AccessResult $expected_access) {
     $account = $this->getMock('\Drupal\Core\Session\AccountInterface');
     $account->expects($this->any())
       ->method('hasPermission')
@@ -843,6 +876,10 @@ public function testAllowedIfHasPermissions($permissions, $conjunction, $expecte
         ['denied', FALSE],
       ]);
 
+    if ($permissions) {
+      $expected_access->cachePerPermissions();
+    }
+
     $access_result = AccessResult::allowedIfHasPermissions($account, $permissions, $conjunction);
     $this->assertEquals($expected_access, $access_result);
   }
@@ -856,14 +893,14 @@ public function providerTestAllowedIfHasPermissions() {
     return [
       [[], 'AND', AccessResult::allowedIf(FALSE)],
       [[], 'OR', AccessResult::allowedIf(FALSE)],
-      [['allowed'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
-      [['allowed'], 'AND', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
-      [['denied'], 'OR', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
-      [['denied'], 'AND', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
-      [['allowed', 'denied'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
-      [['denied', 'allowed'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
-      [['allowed', 'denied', 'other'], 'OR', AccessResult::allowedIf(TRUE)->addCacheContexts(['user.permissions'])],
-      [['allowed', 'denied'], 'AND', AccessResult::allowedIf(FALSE)->addCacheContexts(['user.permissions'])],
+      [['allowed'], 'OR', AccessResult::allowedIf(TRUE)],
+      [['allowed'], 'AND', AccessResult::allowedIf(TRUE)],
+      [['denied'], 'OR', AccessResult::allowedIf(FALSE)],
+      [['denied'], 'AND', AccessResult::allowedIf(FALSE)],
+      [['allowed', 'denied'], 'OR', AccessResult::allowedIf(TRUE)],
+      [['denied', 'allowed'], 'OR', AccessResult::allowedIf(TRUE)],
+      [['allowed', 'denied', 'other'], 'OR', AccessResult::allowedIf(TRUE)],
+      [['allowed', 'denied'], 'AND', AccessResult::allowedIf(FALSE)],
     ];
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php
index bc2e5cc..0788228 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Entity;
 
+use Drupal\Core\DependencyInjection\Container;
 use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\Routing\Route;
 use Drupal\Core\Access\AccessResult;
@@ -25,6 +26,14 @@ class EntityAccessCheckTest extends UnitTestCase {
    * Tests the method for checking access to routes.
    */
   public function testAccess() {
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+
     $route = new Route('/foo', array(), array('_entity_access' => 'node.update'));
     $upcasted_arguments = new ParameterBag();
     $route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
diff --git a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
index c20a99b..c6beb43 100644
--- a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\Core\Menu;
 
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\Core\Menu\DefaultMenuLinkTreeManipulators;
 use Drupal\Core\Menu\MenuLinkTreeElement;
 use Drupal\Tests\UnitTestCase;
@@ -76,6 +77,13 @@ protected function setUp() {
       ->getMock();
 
     $this->defaultMenuTreeManipulators = new DefaultMenuLinkTreeManipulators($this->accessManager, $this->currentUser, $this->queryFactory);
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php
index d818e47..c5f96fb 100644
--- a/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php
+++ b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\Core\Route;
 
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\DependencyInjection\Container;
 use Drupal\Core\Session\UserSession;
 use Drupal\Tests\UnitTestCase;
 use Drupal\user\Access\RoleAccessCheck;
@@ -143,6 +144,14 @@ public function roleAccessProvider() {
    * @dataProvider roleAccessProvider
    */
   public function testRoleAccess($path, $grant_accounts, $deny_accounts) {
+
+    $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+
     $role_access_check = new RoleAccessCheck();
     $collection = $this->getTestRouteCollection();
 
