diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
index 5ee57a0..b3dc04c 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
@@ -50,9 +50,8 @@ function testFieldAttachSaveLoad() {
     $this->createFieldWithInstance('', $entity_type);
     $cardinality = $this->field->getFieldCardinality();
 
-    // Configure the instance so that we test hook_field_load() (see
-    // field_test_field_load() in field_test.module).
-    $this->instance->settings['test_hook_field_load'] = TRUE;
+    // Configure the instance so that we test TestItem::getCacheData().
+    $this->instance->settings['test_cached_data'] = TRUE;
     $this->instance->save();
 
     // TODO : test empty values filtering and "compression" (store consecutive deltas).
@@ -79,7 +78,7 @@ function testFieldAttachSaveLoad() {
     for ($delta = 0; $delta < $cardinality; $delta++) {
       // The field value loaded matches the one inserted or updated.
       $this->assertEqual($entity->{$this->field_name}[$delta]->value , $values[$current_revision][$delta]['value'], format_string('Current revision: expected value %delta was found.', array('%delta' => $delta)));
-      // The value added in hook_field_load() is found.
+      // The value added in TestItem::getCacheData() is found.
       $this->assertEqual($entity->{$this->field_name}[$delta]->additional_key, 'additional_value', format_string('Current revision: extra information for value %delta was found', array('%delta' => $delta)));
     }
 
@@ -132,9 +131,8 @@ function testFieldAttachLoadMultiple() {
           'entity_type' => $entity_type,
           'bundle' => $bundles[$bundle],
           'settings' => array(
-            // Configure the instance so that we test hook_field_load()
-            // (see field_test_field_load() in field_test.module).
-            'test_hook_field_load' => TRUE,
+            // Configure the instance so that we test TestItem::getCacheData().
+            'test_cached_data' => TRUE,
           ),
         ))->save();
       }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index 637aacf..809d0d6 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -23,7 +23,7 @@ public static function getInfo() {
   function testFieldInfo() {
     // Test that field_test module's fields, widgets, and formatters show up.
 
-    $field_test_info = field_test_field_info();
+    $field_test_info = $this->getExpectedFieldTypeDefinition();
     $info = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinitions();
     foreach ($field_test_info as $t_key => $field_type) {
       foreach ($field_type as $key => $val) {
@@ -283,7 +283,7 @@ function testFieldMap() {
    * Test that the field_info settings convenience functions work.
    */
   function testSettingsInfo() {
-    $info = field_test_field_info();
+    $info = $this->getExpectedFieldTypeDefinition();
     foreach ($info as $type => $data) {
       $field_type_manager = \Drupal::service('plugin.manager.entity.field.field_type');
       $this->assertIdentical($field_type_manager->getDefaultSettings($type), $data['settings'], format_string("field settings service returns %type's field settings", array('%type' => $type)));
@@ -327,4 +327,50 @@ function testWidgetDefinition() {
     $this->assertTrue(in_array('test_field', $widget_definition['field_types']), "The 'test_field_widget_multiple' widget is enabled for the 'test_field' field type in field_test_field_widget_info_alter().");
   }
 
+  /**
+   * Returns field info definition.
+   */
+  protected function getExpectedFieldTypeDefinition() {
+    return array(
+      'test_field' => array(
+        'label' => t('Test field'),
+        'description' => t('Dummy field type used for tests.'),
+        'settings' => array(
+          'test_field_setting' => 'dummy test string',
+          'changeable' => 'a changeable field setting',
+          'unchangeable' => 'an unchangeable field setting',
+        ),
+        'instance_settings' => array(
+          'test_instance_setting' => 'dummy test string',
+          'test_cached_data' => FALSE,
+        ),
+        'default_widget' => 'test_field_widget',
+        'default_formatter' => 'field_test_default',
+        'class' => 'Drupal\field_test\Plugin\field\field_type\TestItem',
+      ),
+      'shape' => array(
+        'label' => t('Shape'),
+        'description' => t('Another dummy field type.'),
+        'settings' => array(
+          'foreign_key_name' => 'shape',
+        ),
+        'instance_settings' => array(),
+        'default_widget' => 'test_field_widget',
+        'default_formatter' => 'field_test_default',
+        'class' => 'Drupal\field_test\Plugin\field\field_type\ShapeItem',
+      ),
+      'hidden_test_field' => array(
+        'no_ui' => TRUE,
+        'label' => t('Hidden from UI test field'),
+        'description' => t('Dummy hidden field type used for tests.'),
+        'settings' => array(),
+        'instance_settings' => array(),
+        'default_widget' => 'test_field_widget',
+        'default_formatter' => 'field_test_default',
+        'class' => 'Drupal\field_test\Plugin\field\field_type\HiddenTestItem',
+      ),
+    );
+  }
+
+
 }
diff --git a/core/modules/field/tests/modules/field_test/field_test.field.inc b/core/modules/field/tests/modules/field_test/field_test.field.inc
index 270dc02..cbfe2f4 100644
--- a/core/modules/field/tests/modules/field_test/field_test.field.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.field.inc
@@ -12,51 +12,6 @@
 use Drupal\field\FieldException;
 
 /**
- * Implements hook_field_info().
- */
-function field_test_field_info() {
-  return array(
-    'test_field' => array(
-      'label' => t('Test field'),
-      'description' => t('Dummy field type used for tests.'),
-      'settings' => array(
-        'test_field_setting' => 'dummy test string',
-        'changeable' => 'a changeable field setting',
-        'unchangeable' => 'an unchangeable field setting',
-      ),
-      'instance_settings' => array(
-        'test_instance_setting' => 'dummy test string',
-        'test_hook_field_load' => FALSE,
-      ),
-      'default_widget' => 'test_field_widget',
-      'default_formatter' => 'field_test_default',
-      'class' => 'Drupal\field_test\Type\TestItem',
-    ),
-    'shape' => array(
-      'label' => t('Shape'),
-      'description' => t('Another dummy field type.'),
-      'settings' => array(
-        'foreign_key_name' => 'shape',
-      ),
-      'instance_settings' => array(),
-      'default_widget' => 'test_field_widget',
-      'default_formatter' => 'field_test_default',
-      'class' => 'Drupal\field_test\Type\ShapeItem',
-    ),
-    'hidden_test_field' => array(
-      'no_ui' => TRUE,
-      'label' => t('Hidden from UI test field'),
-      'description' => t('Dummy hidden field type used for tests.'),
-      'settings' => array(),
-      'instance_settings' => array(),
-      'default_widget' => 'test_field_widget',
-      'default_formatter' => 'field_test_default',
-      'class' => 'Drupal\field_test\Type\HiddenTestItem',
-    ),
-  );
-}
-
-/**
  * Implements hook_field_widget_info_alter().
  */
 function field_test_field_widget_info_alter(&$info) {
@@ -73,128 +28,6 @@ function field_test_field_update_forbid($field, $prior_field) {
 }
 
 /**
- * Implements hook_field_load().
- */
-function field_test_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
-  $args = func_get_args();
-  field_test_memorize(__FUNCTION__, $args);
-
-  foreach ($items as $id => $item) {
-    // To keep the test non-intrusive, only act for instances with the
-    // test_hook_field_load setting explicitly set to TRUE.
-    $test_hook_field_load = $instances[$id]->getFieldSetting('test_hook_field_load');
-    if (!empty($test_hook_field_load)) {
-      foreach ($item as $delta => $value) {
-        // Don't add anything on empty values.
-        if ($value) {
-          $items[$id][$delta]['additional_key'] = 'additional_value';
-        }
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_field_insert().
- */
-function field_test_field_insert(EntityInterface $entity, $field, $instance, $items) {
-  $args = func_get_args();
-  field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
- * Implements hook_field_update().
- */
-function field_test_field_update(EntityInterface $entity, $field, $instance, $items) {
-  $args = func_get_args();
-  field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
- * Implements hook_field_delete().
- */
-function field_test_field_delete(EntityInterface $entity, $field, $instance, $items) {
-  $args = func_get_args();
-  field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
- * Implements hook_field_validate().
- *
- * Possible error codes:
- * - 'field_test_invalid': The value is invalid.
- */
-function field_test_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) {
-  $args = func_get_args();
-  field_test_memorize(__FUNCTION__, $args);
-
-  foreach ($items as $delta => $item) {
-    if ($item['value'] == -1) {
-      $errors[$field->getFieldName()][$langcode][$delta][] = array(
-        'error' => 'field_test_invalid',
-        'message' => t('%name does not accept the value -1.', array('%name' => $instance->getFieldLabel())),
-      );
-    }
-  }
-}
-
-/**
- * Implements hook_field_is_empty().
- */
-function field_test_field_is_empty($item, $field_type) {
-  if ($field_type == 'test_field') {
-    return empty($item['value']);
-  }
-  return empty($item['shape']) && empty($item['color']);
-}
-
-/**
- * Implements hook_field_settings_form().
- */
-function field_test_field_settings_form($field, $instance) {
-  $settings = $field->getFieldSettings();
-
-  $form['test_field_setting'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Field test field setting'),
-    '#default_value' => $settings['test_field_setting'],
-    '#required' => FALSE,
-    '#description' => t('A dummy form element to simulate field setting.'),
-  );
-
-  return $form;
-}
-
-/**
- * Implements hook_field_instance_settings_form().
- */
-function field_test_field_instance_settings_form($field, $instance) {
-  $settings = $instance->getFieldSettings();
-
-  $form['test_instance_setting'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Field test field instance setting'),
-    '#default_value' => $settings['test_instance_setting'],
-    '#required' => FALSE,
-    '#description' => t('A dummy form element to simulate field instance setting.'),
-  );
-
-  return $form;
-}
-
-/**
- * Form element validation handler for 'test_field_widget_multiple' widget.
- */
-function field_test_widget_multiple_validate($element, &$form_state) {
-  $values = array_map('trim', explode(',', $element['#value']));
-  $items = array();
-  foreach ($values as $value) {
-    $items[] = array('value' => $value);
-  }
-  form_set_value($element, $items, $form_state);
-}
-
-/**
  * Sample 'default value' callback.
  */
 function field_test_default_value(EntityInterface $entity, $field, $instance) {
diff --git a/core/modules/field/tests/modules/field_test/field_test.install b/core/modules/field/tests/modules/field_test/field_test.install
deleted file mode 100644
index ee2e28d..0000000
--- a/core/modules/field/tests/modules/field_test/field_test.install
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * @file
- * Install, update and uninstall functions for the field_test module.
- */
-
-/**
- * Implements hook_install().
- */
-function field_test_install() {
-  // hook_entity_info_alter() needs to be executed as last.
-  module_set_weight('field_test', 1);
-}
-
-/**
- * Implements hook_field_schema().
- */
-function field_test_field_schema($field) {
-  if ($field->getFieldType() == 'test_field') {
-    return array(
-      'columns' => array(
-        'value' => array(
-          'type' => 'int',
-          'size' => 'medium',
-          'not null' => FALSE,
-        ),
-      ),
-      'indexes' => array(
-        'value' => array('value'),
-      ),
-    );
-  }
-  else {
-    $foreign_keys = array();
-    // The 'foreign keys' key is not always used in tests.
-    $foreign_key_name = $field->getFieldSetting('foreign_key_name');
-    if (!empty($foreign_key_name)) {
-      $foreign_keys['foreign keys'] = array(
-        // This is a dummy foreign key definition, references a table that
-        // doesn't exist, but that's not a problem.
-        $foreign_key_name => array(
-          'table' => $foreign_key_name,
-          'columns' => array($foreign_key_name => 'id'),
-        ),
-      );
-    }
-    return array(
-      'columns' => array(
-        'shape' => array(
-          'type' => 'varchar',
-          'length' => 32,
-          'not null' => FALSE,
-        ),
-        'color' => array(
-          'type' => 'varchar',
-          'length' => 32,
-          'not null' => FALSE,
-        ),
-      ),
-    ) + $foreign_keys;
-  }
-}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Validation/Constraint/TestFieldConstraint.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Validation/Constraint/TestFieldConstraint.php
new file mode 100644
index 0000000..f6661cd
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Validation/Constraint/TestFieldConstraint.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_test\Plugin\Validation\Constraint\TestFieldConstraint.
+ */
+
+namespace Drupal\field_test\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraints\NotEqualTo;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+
+/**
+ * Checks if a value is not equal.
+ *
+ * @Plugin(
+ *   id = "TestField",
+ *   label = @Translation("Test Field", context = "Validation"),
+ *   type = { "integer" }
+ * )
+ */
+class TestFieldConstraint extends NotEqualTo {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRequiredOptions() {
+    return array('value');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validatedBy() {
+    return '\Symfony\Component\Validator\Constraints\NotEqualToValidator';
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/HiddenTestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/HiddenTestItem.php
similarity index 53%
rename from core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/HiddenTestItem.php
rename to core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/HiddenTestItem.php
index 7a9dd30..5d909e4 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/HiddenTestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/HiddenTestItem.php
@@ -2,13 +2,25 @@
 
 /**
  * @file
- * Contains \Drupal\field_test\Type\HiddenTestItem.
+ * Contains \Drupal\field_test\Plugin\field\field_type\HiddenTestItem.
  */
 
-namespace Drupal\field_test\Type;
+namespace Drupal\field_test\Plugin\field\field_type;
+
+use Drupal\Core\Entity\Annotation\FieldType;
+use Drupal\Core\Annotation\Translation;
 
 /**
- * Defines the 'test_field' entity field item.
+ * Defines the 'hidden_test' entity field item.
+ *
+ * @FieldType(
+ *   id = "hidden_test_field",
+ *   label = @Translation("Hidden from UI test field"),
+ *   description = @Translation("Dummy hidden field type used for tests."),
+ *   no_ui = TRUE,
+ *   default_widget = "test_field_widget",
+ *   default_formatter = "field_test_default"
+ * )
  */
 class HiddenTestItem extends TestItem {
 
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/ShapeItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/ShapeItem.php
new file mode 100644
index 0000000..88abb7a
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/ShapeItem.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_test\Plugin\field\field_type\ShapeItem.
+ */
+
+namespace Drupal\field_test\Plugin\field\field_type;
+
+use Drupal\Core\Entity\Annotation\FieldType;
+use Drupal\Core\Annotation\Translation;
+use Drupal\field\FieldInterface;
+use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase;
+
+/**
+ * Defines the 'shape_field' entity field item.
+ *
+ * @FieldType(
+ *   id = "shape",
+ *   label = @Translation("Shape"),
+ *   description = @Translation("Another dummy field type."),
+ *   settings = {
+ *     "foreign_key_name" = "shape"
+ *   },
+ *   default_widget = "test_field_widget",
+ *   default_formatter = "field_test_default"
+ * )
+ */
+class ShapeItem extends ConfigFieldItemBase {
+
+  /**
+   * Property definitions of the contained properties.
+   *
+   * @see ShapeItem::getPropertyDefinitions()
+   *
+   * @var array
+   */
+  static $propertyDefinitions;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropertyDefinitions() {
+
+    if (!isset(static::$propertyDefinitions)) {
+      static::$propertyDefinitions['shape'] = array(
+        'type' => 'string',
+        'label' => t('Shape'),
+      );
+      static::$propertyDefinitions['color'] = array(
+        'type' => 'string',
+        'label' => t('Color'),
+      );
+    }
+    return static::$propertyDefinitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldInterface $field) {
+    $foreign_keys = array();
+    // The 'foreign keys' key is not always used in tests.
+    if ($field->getFieldSetting('foreign_key_name')) {
+      $foreign_keys['foreign keys'] = array(
+        // This is a dummy foreign key definition, references a table that
+        // doesn't exist, but that's not a problem.
+        $field->getFieldSetting('foreign_key_name') => array(
+          'table' => $field->getFieldSetting('foreign_key_name'),
+          'columns' => array($field->getFieldSetting('foreign_key_name') => 'id'),
+        ),
+      );
+    }
+    return array(
+      'columns' => array(
+        'shape' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => FALSE,
+        ),
+        'color' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => FALSE,
+        ),
+      ),
+    ) + $foreign_keys;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    $item = $this->getValue();
+    return empty($item['shape']) && empty($item['color']);
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/TestItem.php
new file mode 100644
index 0000000..396abc4
--- /dev/null
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/field_type/TestItem.php
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_test\Plugin\field\field_type\TestItem.
+ */
+
+namespace Drupal\field_test\Plugin\field\field_type;
+
+use Drupal\Core\Entity\Annotation\FieldType;
+use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\Field\PrepareCacheInterface;
+use Drupal\field\FieldInterface;
+use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase;
+
+/**
+ * Defines the 'test_field' entity field item.
+ *
+ * @FieldType(
+ *   id = "test_field",
+ *   label = @Translation("Test field"),
+ *   description = @Translation("Dummy field type used for tests."),
+ *   settings = {
+ *     "test_field_setting" = "dummy test string",
+ *     "changeable" =  "a changeable field setting",
+ *     "unchangeable" = "an unchangeable field setting"
+ *   },
+ *   instance_settings = {
+ *     "test_instance_setting" = "dummy test string",
+ *     "test_cached_data" = FALSE
+ *   },
+ *   default_widget = "test_field_widget",
+ *   default_formatter = "field_test_default"
+ * )
+ */
+class TestItem extends ConfigFieldItemBase implements PrepareCacheInterface {
+
+  /**
+   * Property definitions of the contained properties.
+   *
+   * @see TestItem::getPropertyDefinitions()
+   *
+   * @var array
+   */
+  static $propertyDefinitions;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropertyDefinitions() {
+
+    if (!isset(static::$propertyDefinitions)) {
+      static::$propertyDefinitions['value'] = array(
+        'type' => 'integer',
+        'label' => t('Test integer value'),
+      );
+    }
+    return static::$propertyDefinitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldInterface $field) {
+    return array(
+      'columns' => array(
+        'value' => array(
+          'type' => 'int',
+          'size' => 'medium',
+          'not null' => FALSE,
+        ),
+      ),
+      'indexes' => array(
+        'value' => array('value'),
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state, $has_data) {
+    $form['test_field_setting'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Field test field setting'),
+      '#default_value' => $this->getFieldSetting('test_field_setting'),
+      '#required' => FALSE,
+      '#description' => t('A dummy form element to simulate field setting.'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function instanceSettingsForm(array $form, array &$form_state) {
+    $form['test_instance_setting'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Field test field instance setting'),
+      '#default_value' => $this->getFieldSetting('test_instance_setting'),
+      '#required' => FALSE,
+      '#description' => t('A dummy form element to simulate field instance setting.'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheData() {
+    // To keep the test non-intrusive, only act for instances with the
+    // 'test_cached_data' setting explicitly set to TRUE. Also don't add
+    // anything on empty values.
+    if ($this->getFieldSetting('test_cached_data') && $this->getValue()) {
+      // Set the additional value so that getValue() will return it.
+      $this->additional_key = 'additional_value';
+    }
+    return $this->getValue();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete() {
+    // Reports that delete() method is executed for testing purposes.
+    field_test_memorize('field_test_field_delete', array($this->getEntity()));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConstraints() {
+    $constraint_manager = \Drupal::typedData()->getValidationConstraintManager();
+    $constraints = parent::getConstraints();
+
+    $constraints[] = $constraint_manager->create('ComplexData', array(
+      'value' => array(
+        'TestField' => array(
+          'value' => -1,
+          'message' => t('%name does not accept the value @value.', array('%name' => $this->getFieldDefinition()->getFieldLabel(), '@value' => -1)),
+        )
+      ),
+    ));
+
+    return $constraints;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    return empty($this->value);
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
index 0b9a73c..d5c0269 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
@@ -66,7 +66,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     $element += array(
       '#type' => 'textfield',
       '#default_value' => implode(', ', $values),
-      '#element_validate' => array('field_test_widget_multiple_validate'),
+      '#element_validate' => array(array(get_class($this), 'multipleValidate')),
     );
     return $element;
   }
@@ -78,4 +78,16 @@ public function errorElement(array $element, ConstraintViolationInterface $error
     return $element;
   }
 
+  /**
+   * Element validation helper.
+   */
+  public static function multipleValidate($element, &$form_state) {
+    $values = array_map('trim', explode(',', $element['#value']));
+    $items = array();
+    foreach ($values as $value) {
+      $items[] = array('value' => $value);
+    }
+    form_set_value($element, $items, $form_state);
+  }
+
 }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/ShapeItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/ShapeItem.php
deleted file mode 100644
index 4c0d4c9..0000000
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/ShapeItem.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\field_test\Type\ShapeItem.
- */
-
-namespace Drupal\field_test\Type;
-
-use Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem;
-
-/**
- * Defines the 'shape_field' entity field item.
- */
-class ShapeItem extends LegacyConfigFieldItem {
-
-  /**
-   * Property definitions of the contained properties.
-   *
-   * @see ShapeItem::getPropertyDefinitions()
-   *
-   * @var array
-   */
-  static $propertyDefinitions;
-
-  /**
-   * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
-   */
-  public function getPropertyDefinitions() {
-
-    if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['shape'] = array(
-        'type' => 'string',
-        'label' => t('Shape'),
-      );
-      static::$propertyDefinitions['color'] = array(
-        'type' => 'string',
-        'label' => t('Color'),
-      );
-    }
-    return static::$propertyDefinitions;
-  }
-
-}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/TestItem.php
deleted file mode 100644
index 20c34e3..0000000
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Type/TestItem.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\field_test\Type\TestItem.
- */
-
-namespace Drupal\field_test\Type;
-
-use Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem;
-
-/**
- * Defines the 'test_field' entity field item.
- */
-class TestItem extends LegacyConfigFieldItem {
-
-  /**
-   * Property definitions of the contained properties.
-   *
-   * @see TestItem::getPropertyDefinitions()
-   *
-   * @var array
-   */
-  static $propertyDefinitions;
-
-  /**
-   * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
-   */
-  public function getPropertyDefinitions() {
-
-    if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'integer',
-        'label' => t('Test integer value'),
-      );
-    }
-    return static::$propertyDefinitions;
-  }
-
-}
