diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc
index 4cea03a..09fdc8e 100644
--- a/core/modules/field/tests/modules/field_test/field_test.entity.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc
@@ -40,71 +40,3 @@ function field_test_entity_info_translatable($entity_type = NULL, $translatable
   }
   return $stored_value;
 }
-
-/**
- * Form combining two separate entities.
- */
-function field_test_entity_nested_form($form, &$form_state, $entity_1, $entity_2) {
-  // First entity.
-  foreach (array('id', 'type') as $key) {
-    $form[$key] = array(
-      '#type' => 'value',
-      '#value' => $entity_1->$key->value,
-    );
-  }
-  $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle(), 'default');
-  field_attach_form($entity_1, $form, $form_state);
-
-  // Second entity.
-  $form['entity_2'] = array(
-    '#type' => 'details',
-    '#title' => t('Second entity'),
-    '#tree' => TRUE,
-    '#parents' => array('entity_2'),
-    '#weight' => 50,
-  );
-  foreach (array('id', 'type') as $key) {
-    $form['entity_2'][$key] = array(
-      '#type' => 'value',
-      '#value' => $entity_2->$key->value,
-    );
-  }
-  $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle(), 'default');
-  field_attach_form($entity_2, $form['entity_2'], $form_state);
-
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-    '#weight' => 100,
-  );
-
-  return $form;
-}
-
-/**
- * Validate handler for field_test_entity_nested_form().
- */
-function field_test_entity_nested_form_validate($form, &$form_state) {
-  $entity_1 = entity_create('entity_test', $form_state['values']);
-  field_attach_extract_form_values($entity_1, $form, $form_state);
-  field_attach_form_validate($entity_1, $form, $form_state);
-
-  $entity_2 = entity_create('entity_test', $form_state['values']['entity_2']);
-  field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
-  field_attach_form_validate($entity_2, $form['entity_2'], $form_state);
-}
-
-/**
- * Submit handler for field_test_entity_nested_form().
- */
-function field_test_entity_nested_form_submit($form, &$form_state) {
-  $entity_1 = entity_create('entity_test', $form_state['values']);
-  field_attach_extract_form_values($entity_1, $form, $form_state);
-  $entity_1->save();
-
-  $entity_2 = entity_create('entity_test', $form_state['values']['entity_2']);
-  field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
-  $entity_2->save();
-
-  drupal_set_message(t('test_entities @id_1 and @id_2 have been updated.', array('@id_1' => $entity_1->id(), '@id_2' => $entity_2->id())));
-}
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 5ac9e9d..21c67eb 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -44,9 +44,7 @@ function field_test_menu() {
   $items = array();
   $items['test-entity/nested/%entity_test/%entity_test'] = array(
     'title' => 'Nested entity form',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('field_test_entity_nested_form', 2, 3),
-    'access arguments' => array('administer entity_test content'),
+    'route_name' => 'field_test_entity_nested_form',
     'type' => MENU_NORMAL_ITEM,
   );
 
diff --git a/core/modules/field/tests/modules/field_test/field_test.routing.yml b/core/modules/field/tests/modules/field_test/field_test.routing.yml
new file mode 100644
index 0000000..95a9e5d
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/field_test.routing.yml
@@ -0,0 +1,6 @@
+field_test_entity_nested_form:
+  pattern: 'test-entity/nested/{entity_1}/{entity_2}'
+  defaults:
+    _form: '\Drupal\field_test\Form\EntityNestedForm'
+  requirements:
+    _permission: 'administer entity_test content'
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Form/EntityNestedForm.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Form/EntityNestedForm.php
new file mode 100644
index 0000000..57831dd
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Form/EntityNestedForm.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_test\Form\EntityNestedForm.
+ */
+
+namespace Drupal\field_test\Form;
+
+use Drupal\Core\Controller\ControllerInterface;
+use Drupal\Core\Form\FormInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\entity_test\Plugin\Core\Entity\EntityTest;
+
+/**
+ * Displays banned IP addresses.
+ */
+class EntityNestedForm implements FormInterface, ControllerInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static();
+  }
+
+  /**
+   * Constructs an EntityNestedForm object.
+   */
+  public function __construct() {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'field_test_entity_nested_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param Drupal\entity_test\Plugin\Core\Entity\EntityTest $entity_1
+   *   The first entity.
+   * @param Drupal\entity_test\Plugin\Core\Entity\EntityTest $entity_2
+   *   The second entity.
+   */
+  public function buildForm(array $form, array &$form_state, $entity_1 = NULL, $entity_2 = NULL) {
+    // First entity.
+    foreach (array('id', 'type') as $key) {
+      $form[$key] = array(
+        '#type' => 'value',
+        '#value' => $entity_1->$key->value,
+      );
+    }
+    $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle(), 'default');
+    field_attach_form($entity_1, $form, $form_state);
+
+    // Second entity.
+    $form['entity_2'] = array(
+      '#type' => 'details',
+      '#title' => t('Second entity'),
+      '#tree' => TRUE,
+      '#parents' => array('entity_2'),
+      '#weight' => 50,
+    );
+    foreach (array('id', 'type') as $key) {
+      $form['entity_2'][$key] = array(
+        '#type' => 'value',
+        '#value' => $entity_2->$key->value,
+      );
+    }
+    $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle(), 'default');
+    field_attach_form($entity_2, $form['entity_2'], $form_state);
+
+    $form['save'] = array(
+      '#type' => 'submit',
+      '#value' => t('Save'),
+      '#weight' => 100,
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+    $entity_1 = entity_create('entity_test', $form_state['values']);
+    field_attach_extract_form_values($entity_1, $form, $form_state);
+    field_attach_form_validate($entity_1, $form, $form_state);
+
+    $entity_2 = entity_create('entity_test', $form_state['values']['entity_2']);
+    field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
+    field_attach_form_validate($entity_2, $form['entity_2'], $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $entity_1 = entity_create('entity_test', $form_state['values']);
+    field_attach_extract_form_values($entity_1, $form, $form_state);
+    $entity_1->save();
+
+    $entity_2 = entity_create('entity_test', $form_state['values']['entity_2']);
+    field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
+    $entity_2->save();
+
+    drupal_set_message(t('test_entities @id_1 and @id_2 have been updated.', array('@id_1' => $entity_1->id(), '@id_2' => $entity_2->id())));
+  }
+
+}
