diff --git a/core/modules/system/tests/modules/database_test/database_test.module b/core/modules/system/tests/modules/database_test/database_test.module
index b390004..72963b4 100644
--- a/core/modules/system/tests/modules/database_test/database_test.module
+++ b/core/modules/system/tests/modules/database_test/database_test.module
@@ -48,26 +48,6 @@ function database_test_query_database_test_alter_remove_range_alter(AlterableInt
  * Implements hook_menu().
  */
 function database_test_menu() {
-  $items['database_test/db_query_temporary'] = array(
-    'access callback' => TRUE,
-    'page callback' => 'database_test_db_query_temporary',
-  );
-  $items['database_test/pager_query_even'] = array(
-    'access callback' => TRUE,
-    'page callback' => 'database_test_even_pager_query',
-  );
-  $items['database_test/pager_query_odd'] = array(
-    'access callback' => TRUE,
-    'page callback' => 'database_test_odd_pager_query',
-  );
-  $items['database_test/tablesort'] = array(
-    'access callback' => TRUE,
-    'page callback' => 'database_test_tablesort',
-  );
-  $items['database_test/tablesort_first'] = array(
-    'access callback' => TRUE,
-    'page callback' => 'database_test_tablesort_first',
-  );
   $items['database_test/tablesort_default_sort'] = array(
     'access callback' => TRUE,
     'page callback' => 'drupal_get_form',
@@ -77,132 +57,6 @@ function database_test_menu() {
 }
 
 /**
- * Runs db_query_temporary() and outputs the table name and its number of rows.
- *
- * We need to test that the table created is temporary, so we run it here, in a
- * separate menu callback request; After this request is done, the temporary
- * table should automatically dropped.
- */
-function database_test_db_query_temporary() {
-  $table_name = db_query_temporary('SELECT age FROM {test}', array());
-  return new JsonResponse(array(
-    'table_name' => $table_name,
-    'row_count' => db_select($table_name)->countQuery()->execute()->fetchField(),
-  ));
-}
-
-/**
- * Runs a pager query and returns the results.
- *
- * This function does care about the page GET parameter, as set by the
- * simpletest HTTP call.
- */
-function database_test_even_pager_query($limit) {
-
-  $query = db_select('test', 't');
-  $query
-    ->fields('t', array('name'))
-    ->orderBy('age');
-
-  // This should result in 2 pages of results.
-  $query = $query
-    ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
-    ->limit($limit);
-
-  $names = $query->execute()->fetchCol();
-
-  return new JsonResponse(array(
-    'names' => $names,
-  ));
-}
-
-/**
- * Runs a pager query and returns the results.
- *
- * This function does care about the page GET parameter, as set by the
- * simpletest HTTP call.
- */
-function database_test_odd_pager_query($limit) {
-
-  $query = db_select('test_task', 't');
-  $query
-    ->fields('t', array('task'))
-    ->orderBy('pid');
-
-  // This should result in 4 pages of results.
-  $query = $query
-    ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
-    ->limit($limit);
-
-  $names = $query->execute()->fetchCol();
-
-  return new JsonResponse(array(
-    'names' => $names,
-  ));
-}
-
-/**
- * Runs a tablesort query and returns the results.
- *
- * This function does care about the page GET parameter, as set by the
- * simpletest HTTP call.
- */
-function database_test_tablesort() {
-  $header = array(
-    'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
-    'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
-    'task' => array('data' => t('Task'), 'field' => 'task'),
-    'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
-  );
-
-  $query = db_select('test_task', 't');
-  $query
-    ->fields('t', array('tid', 'pid', 'task', 'priority'));
-
-  $query = $query
-    ->extend('Drupal\Core\Database\Query\TableSortExtender')
-    ->orderByHeader($header);
-
-  // We need all the results at once to check the sort.
-  $tasks = $query->execute()->fetchAll();
-
-  return new JsonResponse(array(
-    'tasks' => $tasks,
-  ));
-}
-
-/**
- * Runs a tablesort query with a second order_by after and returns the results.
- *
- * This function does care about the page GET parameter, as set by the
- * simpletest HTTP call.
- */
-function database_test_tablesort_first() {
-  $header = array(
-    'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
-    'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
-    'task' => array('data' => t('Task'), 'field' => 'task'),
-    'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
-  );
-
-  $query = db_select('test_task', 't');
-  $query
-    ->fields('t', array('tid', 'pid', 'task', 'priority'));
-
-  $query = $query
-    ->extend('Drupal\Core\Database\Query\TableSortExtender')
-    ->orderByHeader($header)
-    ->orderBy('priority');
-
-  // We need all the results at once to check the sort.
-  $tasks = $query->execute()->fetchAll();
-
-  return new JsonResponse(array(
-    'tasks' => $tasks,
-  ));
-}
-
-/**
  * Outputs a form without setting a header sort.
  */
 function database_test_theme_tablesort($form, &$form_state) {
diff --git a/core/modules/system/tests/modules/database_test/database_test.routing.yml b/core/modules/system/tests/modules/database_test/database_test.routing.yml
new file mode 100644
index 0000000..688b341
--- /dev/null
+++ b/core/modules/system/tests/modules/database_test/database_test.routing.yml
@@ -0,0 +1,30 @@
+database_test_db_query_temporary:
+  pattern: 'database_test/db_query_temporary'
+  defaults:
+    _controller: '\Drupal\database_test\Controller\DatabaseTestJsonController::dbQueryTemporary'
+  requirements:
+    _access: 'TRUE'
+database_test_even_pager_query:
+  pattern: 'database_test/pager_query_even'
+  defaults:
+    _controller: '\Drupal\database_test\Controller\DatabaseTestJsonController::evenPagerQuery'
+  requirements:
+    _access: 'TRUE'
+database_test_odd_pager_query:
+  pattern: 'database_test/pager_query_odd'
+  defaults:
+    _controller: '\Drupal\database_test\Controller\DatabaseTestJsonController::oddPagerQuery'
+  requirements:
+    _access: 'TRUE'
+database_test_tablesort:
+  pattern: 'database_test/tablesort'
+  defaults:
+    _controller: '\Drupal\database_test\Controller\DatabaseTestJsonController::tablesort'
+  requirements:
+    _access: 'TRUE'
+database_test_tablesort_first:
+  pattern: 'database_test/tablesort_first'
+  defaults:
+    _controller: '\Drupal\database_test\Controller\DatabaseTestJsonController::tablesortFirst'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/database_test/lib/Drupal/database_test/Controller/DatabaseTestJsonController.php b/core/modules/system/tests/modules/database_test/lib/Drupal/database_test/Controller/DatabaseTestJsonController.php
new file mode 100644
index 0000000..388a838
--- /dev/null
+++ b/core/modules/system/tests/modules/database_test/lib/Drupal/database_test/Controller/DatabaseTestJsonController.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\database_test\Controller\DatabaseTestJsonController.
+ */
+
+namespace Drupal\database_test\Controller;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+class DatabaseTestJsonController {
+
+  /**
+   * Runs db_query_temporary() and outputs the table name and its number of rows.
+   *
+   * We need to test that the table created is temporary, so we run it here, in a
+   * separate menu callback request; After this request is done, the temporary
+   * table should automatically dropped.
+   */
+  public function dbQueryTemporary() {
+    $table_name = db_query_temporary('SELECT age FROM {test}', array());
+    return new JsonResponse(array(
+      'table_name' => $table_name,
+      'row_count' => db_select($table_name)->countQuery()->execute()->fetchField(),
+    ));
+  }
+
+  /**
+   * Runs a pager query and returns the results.
+   *
+   * This function does care about the page GET parameter, as set by the
+   * simpletest HTTP call.
+   */
+  public function evenPagerQuery() {
+    $query = db_select('test', 't');
+    $query
+      ->fields('t', array('name'))
+      ->orderBy('age');
+
+    // This should result in 2 pages of results.
+    $query = $query
+      ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
+      ->limit($limit);
+
+    $names = $query->execute()->fetchCol();
+
+    return new JsonResponse(array(
+      'names' => $names,
+    ));
+  }
+
+  /**
+   * Runs a pager query and returns the results.
+   *
+   * This function does care about the page GET parameter, as set by the
+   * simpletest HTTP call.
+   */
+  public function oddPagerQuery() {
+    $query = db_select('test_task', 't');
+    $query
+      ->fields('t', array('task'))
+      ->orderBy('pid');
+
+    // This should result in 4 pages of results.
+    $query = $query
+      ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
+      ->limit($limit);
+
+    $names = $query->execute()->fetchCol();
+
+    return new JsonResponse(array(
+      'names' => $names,
+    ));
+  }
+
+  /**
+   * Runs a tablesort query and returns the results.
+   *
+   * This function does care about the page GET parameter, as set by the
+   * simpletest HTTP call.
+   */
+  public function tablesort() {
+    $header = array(
+      'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
+      'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
+      'task' => array('data' => t('Task'), 'field' => 'task'),
+      'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
+    );
+
+    $query = db_select('test_task', 't');
+    $query
+      ->fields('t', array('tid', 'pid', 'task', 'priority'));
+
+    $query = $query
+      ->extend('Drupal\Core\Database\Query\TableSortExtender')
+      ->orderByHeader($header);
+
+    // We need all the results at once to check the sort.
+    $tasks = $query->execute()->fetchAll();
+
+    return new JsonResponse(array(
+      'tasks' => $tasks,
+    ));
+  }
+
+  /**
+   * Runs a tablesort query with a second order_by after and returns the results.
+   *
+   * This function does care about the page GET parameter, as set by the
+   * simpletest HTTP call.
+   */
+  public function tablesortFirst() {
+    $header = array(
+      'tid' => array('data' => t('Task ID'), 'field' => 'tid', 'sort' => 'desc'),
+      'pid' => array('data' => t('Person ID'), 'field' => 'pid'),
+      'task' => array('data' => t('Task'), 'field' => 'task'),
+      'priority' => array('data' => t('Priority'), 'field' => 'priority', ),
+    );
+
+    $query = db_select('test_task', 't');
+    $query
+      ->fields('t', array('tid', 'pid', 'task', 'priority'));
+
+    $query = $query
+      ->extend('Drupal\Core\Database\Query\TableSortExtender')
+      ->orderByHeader($header)
+      ->orderBy('priority');
+
+    // We need all the results at once to check the sort.
+    $tasks = $query->execute()->fetchAll();
+
+    return new JsonResponse(array(
+      'tasks' => $tasks,
+    ));
+  }
+
+}
