diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.module b/core/modules/system/tests/modules/ajax_test/ajax_test.module
index e358018..c3c54b0 100644
--- a/core/modules/system/tests/modules/ajax_test/ajax_test.module
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.module
@@ -6,33 +6,17 @@
  */
 
 use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\AlertCommand;
 use Drupal\Core\Ajax\OpenDialogCommand;
 use Drupal\Core\Ajax\OpenModalDialogCommand;
-use Drupal\Core\Ajax\CloseDialogCommand;
-use Drupal\Core\Ajax\HtmlCommand;
 
 /**
  * Implements hook_menu().
  */
 function ajax_test_menu() {
-  $items['ajax-test/render'] = array(
-    'title' => 'ajax_render',
-    'page callback' => 'ajax_test_render',
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-  );
-  $items['ajax-test/order'] = array(
+  $items[] = array(
     'title' => 'AJAX commands order',
-    'page callback' => 'ajax_test_order',
+    'route_name' => 'ajax_test_dialog_render',
     'theme callback' => 'ajax_base_page_theme',
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-  );
-  $items['ajax-test/render-error'] = array(
-    'title' => 'ajax_render_error',
-    'page callback' => 'ajax_test_error',
-    'access callback' => TRUE,
     'type' => MENU_CALLBACK,
   );
   $items['ajax-test/dialog'] = array(
@@ -40,12 +24,6 @@ function ajax_test_menu() {
     'page callback' => 'ajax_test_dialog',
     'access callback' => TRUE,
   );
-  $items['ajax-test/dialog-close'] = array(
-    'title' => 'AJAX Dialog close',
-    'page callback' => 'ajax_test_dialog_close',
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-  );
   return $items;
 }
 
@@ -58,53 +36,6 @@ function ajax_test_system_theme_info() {
 }
 
 /**
- * Menu callback: Returns an element suitable for use by ajax_render().
- *
- * Additionally ensures that ajax_render() incorporates JavaScript settings
- * generated during the page request by invoking drupal_add_js() with a dummy
- * setting.
- */
-function ajax_test_render() {
-  drupal_add_js(array('ajax' => 'test'), 'setting');
-  $response = new AjaxResponse();
-  return $response;
-}
-
-/**
- * Menu callback: Returns an AjaxResponse; settings command set last.
- *
- * Helps verifying AjaxResponse reorders commands to ensure correct execution.
- */
-function ajax_test_order() {
-  $response = new AjaxResponse();
-  $path = drupal_get_path('module', 'system');
-  // HTML insertion command.
-  $response->addCommand(new HtmlCommand('body', 'Hello, world!'));
-  // Add two CSS files (order should remain the same).
-  drupal_add_css($path . '/css/system.admin.css');
-  drupal_add_css($path . '/css/system.maintenance.css');
-  // Add two JavaScript files (first to the footer, should appear last).
-  drupal_add_js($path . '/system.modules.js', array('scope' => 'footer'));
-  drupal_add_js($path . '/system.js');
-  // Finally, add a JavaScript setting.
-  drupal_add_js(array('ajax' => 'test'), 'setting');
-  return $response;
-}
-
-/**
- * Menu callback: Returns AJAX element with #error property set.
- */
-function ajax_test_error() {
-  $message = '';
-  if (!empty($_GET['message'])) {
-    $message = $_GET['message'];
-  }
-  $response = new AjaxResponse();
-  $response->addCommand(new AlertCommand($message));
-  return $response;
-}
-
-/**
  * Menu callback: Renders a form elements and links with #ajax['dialog'].
  */
 function ajax_test_dialog() {
@@ -290,12 +221,3 @@ function ajax_test_dialog_contents() {
 
   return $content;
 }
-
-/**
- * Menu callback: Close the ajax dialog.
- */
-function ajax_test_dialog_close() {
-  $response = new AjaxResponse();
-  $response->addCommand(new CloseDialogCommand('#ajax-test-dialog-wrapper-1'));
-  return $response;
-}
diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml b/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
index 04a0f6d..d62d52d 100644
--- a/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.routing.yml
@@ -4,9 +4,38 @@ ajax_test_dialog_contents:
     _content: '\Drupal\ajax_test\AjaxTestController::dialogContents'
   requirements:
     _access: 'TRUE'
+
 ajax_test_dialog_form:
   pattern: ajax-test/dialog-form
   defaults:
     _form: '\Drupal\ajax_test\AjaxTestForm'
   requirements:
     _access: 'TRUE'
+
+ajax_test_dialog_close:
+  pattern: 'ajax-test/dialog-close'
+  defaults:
+    _controller: '\Drupal\ajax_test\Controller\AjaxTestAjaxController::dialogClose'
+  requirements:
+    _access: 'TRUE'
+
+ajax_test_dialog_render:
+  pattern: 'ajax-test/render'
+  defaults:
+    _controller: '\Drupal\ajax_test\Controller\AjaxTestAjaxController::dialogRender'
+  requirements:
+    _access: 'TRUE'
+
+ajax_test_dialog_order:
+  pattern: 'ajax-test/order'
+  defaults:
+    _controller: '\Drupal\ajax_test\Controller\AjaxTestAjaxController::dialogOrder'
+  requirements:
+    _access: 'TRUE'
+
+ajax_test_dialog_error:
+  pattern: 'ajax-test/render-error'
+  defaults:
+    _controller: '\Drupal\ajax_test\Controller\AjaxTestAjaxController::dialogError'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/ajax_test/lib/Drupal/ajax_test/Controller/AjaxTestAjaxController.php b/core/modules/system/tests/modules/ajax_test/lib/Drupal/ajax_test/Controller/AjaxTestAjaxController.php
new file mode 100644
index 0000000..b8cd012
--- /dev/null
+++ b/core/modules/system/tests/modules/ajax_test/lib/Drupal/ajax_test/Controller/AjaxTestAjaxController.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @file
+ */
+
+namespace Drupal\ajax_test\Controller;
+
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\AlertCommand;
+use Drupal\Core\Ajax\CloseDialogCommand;
+use Drupal\Core\Ajax\HtmlCommand;
+use Drupal\Core\Controller\ControllerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+class AjaxTestAjaxController implements ControllerInterface {
+
+  /**
+   * Close the ajax dialog.
+   */
+  public function dialogClose() {
+    drupal_set_title('AJAX Dialog close');
+
+    $response = new AjaxResponse();
+    $response->addCommand(new CloseDialogCommand('#ajax-test-dialog-wrapper-1'));
+    return $response;
+  }
+
+  /**
+   * Returns an element suitable for use by ajax_render().
+   *
+   * Additionally ensures that ajax_render() incorporates JavaScript settings
+   * generated during the page request by invoking drupal_add_js() with a dummy
+   * setting.
+   */
+  public function dialogRender() {
+    drupal_add_js(array('ajax' => 'test'), 'setting');
+    $response = new AjaxResponse();
+    return $response;
+  }
+
+  /**
+   * Returns an AjaxResponse; settings command set last.
+   *
+   * Helps verifying AjaxResponse reorders commands to ensure correct execution.
+   */
+  public function dialogOrder() {
+    $response = new AjaxResponse();
+    $path = drupal_get_path('module', 'system');
+    // HTML insertion command.
+    $response->addCommand(new HtmlCommand('body', 'Hello, world!'));
+    // Add two CSS files (order should remain the same).
+    drupal_add_css($path . '/css/system.admin.css');
+    drupal_add_css($path . '/css/system.maintenance.css');
+    // Add two JavaScript files (first to the footer, should appear last).
+    drupal_add_js($path . '/system.modules.js', array('scope' => 'footer'));
+    drupal_add_js($path . '/system.js');
+    // Finally, add a JavaScript setting.
+    drupal_add_js(array('ajax' => 'test'), 'setting');
+    return $response;
+  }
+
+  /**
+   * Returns AJAX element with #error property set.
+   */
+  public function dialogError(Request $request) {
+    $message = '';
+    if (!empty($request->query->get('message'))) {
+      $message = $request->query->get('message');
+    }
+    $response = new AjaxResponse();
+    $response->addCommand(new AlertCommand($message));
+    return $response;
+  }
+}
