diff --git a/modules/authcache_enum/lib/Drupal/authcache_enum/Tests/AuthcacheEnumKeysTestCase.php b/modules/authcache_enum/lib/Drupal/authcache_enum/Tests/AuthcacheEnumKeysTestCase.php
index 03e1a0a..d822c7e 100644
--- a/modules/authcache_enum/lib/Drupal/authcache_enum/Tests/AuthcacheEnumKeysTestCase.php
+++ b/modules/authcache_enum/lib/Drupal/authcache_enum/Tests/AuthcacheEnumKeysTestCase.php
@@ -25,7 +25,26 @@ class AuthcacheEnumKeysTestCase extends \DrupalWebTestCase {
    * {@inheritdoc}
    */
   public function setUp() {
-    parent::setUp('authcache_enum');
+    parent::setUp('authcache_enum', 'authcache_enum_test');
+
+    // HookStub.
+    $this->stubmod = new \ModuleStub('authcache_enum_test');
+  }
+
+  /**
+   * Test whether the given stub passes the invocation verifier.
+   */
+  protected function assertStub(\HookStubProxy $stub, $verifier, $message = NULL) {
+    $result = $stub->verify($verifier, $error);
+
+    if (!$message) {
+      $message = t('Verify invocation of hook @hook.', array('@hook' => $stub->hookname()));
+    }
+    if (!$result && is_string($error)) {
+      $message .= ' ' . $error;
+    }
+
+    $this->assertTRUE($result, $message);
   }
 
   /**
@@ -80,4 +99,129 @@ class AuthcacheEnumKeysTestCase extends \DrupalWebTestCase {
     // * rid1 and rid2
     $this->assertEqual(4, count($result));
   }
+
+  /**
+   * Test anonymous key customization.
+   */
+  public function testCustomAnonymousKeys() {
+    global $base_root;
+
+    $keys = array(
+      $this->randomName(6),
+      $this->randomName(7),
+      $this->randomName(8),
+    );
+
+    $delete_key = $keys[1];
+    $insert_key = $this->randomName(9);
+
+    $alter_keys = array(
+      'delete' => array($base_root, $delete_key),
+      'insert' => array($insert_key),
+    );
+
+    $expected_keys = array(
+      $keys[0],
+      $keys[2],
+      $insert_key,
+    );
+
+    $keystub = $this->stubmod->hook('authcache_enum_anonymous_keys', $keys);
+    $alterstub = $this->stubmod->hook('authcache_enum_anonymous_keys_alter', $alter_keys);
+    $result = authcache_enum_keys();
+    $this->assertStub($keystub, \HookStub::once());
+    $this->assertStub($alterstub, \HookStub::once());
+
+    $this->assertEqual($expected_keys, $result);
+  }
+
+  /**
+   * Test authenticated key customization.
+   */
+  public function testCustomAuthenticatedKeys() {
+    global $base_root;
+
+    $rid1 = (int) $this->drupalCreateRole(array());
+    $rid2 = (int) $this->drupalCreateRole(array());
+    variable_set('authcache_roles', array(
+      DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+      DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID,
+      $rid1 => $rid1,
+      $rid2 => $rid2,
+    ));
+
+    $property_info = array(
+      'js' => array(
+        'name' => t('Browser supports JavaScript'),
+        'choices' => array(TRUE, FALSE),
+      ),
+    );
+
+    $expect_properties = array(
+      array(
+        'base_root' => $base_root,
+        'roles' => array(DRUPAL_AUTHENTICATED_RID),
+        'js' => FALSE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array(DRUPAL_AUTHENTICATED_RID),
+        'js' => TRUE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid1),
+        'js' => FALSE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid1),
+        'js' => TRUE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid2),
+        'js' => FALSE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid2),
+        'js' => TRUE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid1, $rid2),
+        'js' => FALSE,
+      ),
+      array(
+        'base_root' => $base_root,
+        'roles' => array($rid1, $rid2),
+        'js' => TRUE,
+      ),
+    );
+
+    $user_keys = array_map('authcache_user_key', $expect_properties);
+    $expect_alter = array_combine($user_keys, $expect_properties);
+    ksort($expect_alter);
+
+    $expect_keys = $user_keys;
+    $expect_keys[] = $base_root;
+
+    $keystub = $this->stubmod->hook('authcache_enum_key_properties', $property_info);
+    $alterstub = $this->stubmod->hook('authcache_enum_key_properties_alter');
+    $result = authcache_enum_keys();
+    $this->assertStub($keystub, \HookStub::once());
+    $this->assertStub($alterstub, \HookStub::once());
+    $this->assertStub($alterstub, \HookStub::args(array(
+      $expect_alter,
+      NULL,
+      NULL,
+      NULL,
+    )));
+
+    sort($result);
+    sort($expect_keys);
+    $this->assertEqual($expect_keys, $result);
+  }
+
 }
diff --git a/modules/authcache_enum/tests/authcache_enum_test.info b/modules/authcache_enum/tests/authcache_enum_test.info
new file mode 100644
index 0000000..18c28d4
--- /dev/null
+++ b/modules/authcache_enum/tests/authcache_enum_test.info
@@ -0,0 +1,5 @@
+name = Authcache Enum Test Stub
+description = Authcache Enum Test Stub
+core = 7.x
+hidden = TRUE
+dependencies[] = authcache_test_hookstub
diff --git a/modules/authcache_enum/tests/authcache_enum_test.module b/modules/authcache_enum/tests/authcache_enum_test.module
new file mode 100644
index 0000000..4d26b68
--- /dev/null
+++ b/modules/authcache_enum/tests/authcache_enum_test.module
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Stub module for Authcache Enum test.
+ */
+
+
+/**
+ * Implements hook_authcache_enum_anonymous_keys()
+ */
+function authcache_enum_test_authcache_enum_anonymous_keys() {
+  return HookStub::record(__FUNCTION__, func_get_args());
+}
+
+/**
+ * Implements hook_authcache_enum_anonymous_keys_alter()
+ */
+function authcache_enum_test_authcache_enum_anonymous_keys_alter(&$keys) {
+  if (($alter = HookStub::record(__FUNCTION__, func_get_args()))) {
+    $keys = array_diff($keys, $alter['delete']);
+    $keys = array_merge($keys, $alter['insert']);
+  }
+}
+
+/**
+ * Implements hook_authcache_enum_key_properties()
+ */
+function authcache_enum_test_authcache_enum_key_properties() {
+  return HookStub::record(__FUNCTION__, func_get_args());
+}
+
+/**
+ * Implements hook_authcache_enum_key_properties_alter()
+ */
+function authcache_enum_test_authcache_enum_key_properties_alter(&$properties_info) {
+  ksort($properties_info);
+  return HookStub::record(__FUNCTION__, func_get_args());
+}
