diff --git a/src/Entity/Index.php b/src/Entity/Index.php
index 1b710d8..b04628c 100644
--- a/src/Entity/Index.php
+++ b/src/Entity/Index.php
@@ -693,6 +693,8 @@ public function addField(FieldInterface $field) {
       throw new SearchApiException("'$field_id' is a reserved value and cannot be used as the machine name of a normal field.");
     }
 
+    // This will automatically call getFields(), thus initializing
+    // $this->fieldInstances, if that hasn't been done yet.
     $old_field = $this->getField($field_id);
     if ($old_field && $old_field != $field) {
       throw new SearchApiException("Cannot add field with machine name '$field_id': machine name is already taken.");
@@ -1186,12 +1188,31 @@ public function preSave(EntityStorageInterface $storage) {
       $processor->preIndexSave();
     }
 
+    // Write the field and plugin settings to the persistent *_settings
+    // properties.
+    $this->writeChangesToSettings();
+
+    // Since we change dependency-relevant data in this method, we can only call
+    // the parent method at the end (or we'd need to re-calculate the
+    // dependencies).
+    parent::preSave($storage);
+  }
+
+  /**
+   * Prepares for changes to this index to be persisted.
+   *
+   * To this end, the settings for all loaded field and plugin objects are
+   * written back to the corresponding *_settings properties.
+   *
+   * @return $this
+   */
+  protected function writeChangesToSettings() {
     // Calculate field dependencies and save field settings containing them.
     $fields = $this->getFields();
     $field_dependencies = $this->getFieldDependencies();
     $field_dependencies += array_fill_keys(array_keys($fields), array());
     $this->field_settings = array();
-    foreach ($this->getFields() as $field_id => $field) {
+    foreach ($fields as $field_id => $field) {
       $field->setDependencies($field_dependencies[$field_id]);
       $this->field_settings[$field_id] = $field->getSettings();
     }
@@ -1225,10 +1246,7 @@ public function preSave(EntityStorageInterface $storage) {
       );
     }
 
-    // Since we change dependency-relevant data in this method, we can only call
-    // the parent method at the end (or we'd need to re-calculate the
-    // dependencies).
-    parent::preSave($storage);
+    return $this;
   }
 
   /**
@@ -1835,6 +1853,14 @@ protected function getAllPlugins() {
    * Prevents the instantiated plugins and fields from being serialized.
    */
   public function __sleep() {
+    // First, write our changes to the persistent *_settings properties so they
+    // won't be discarded. Make sure we have a container to do this. This is
+    // important to correctly display test failures.
+    if (\Drupal::hasContainer()) {
+      $this->writeChangesToSettings();
+    }
+
+    // Then, return a list of all properties that don't contain objects.
     $properties = get_object_vars($this);
     unset($properties['datasourceInstances']);
     unset($properties['trackerInstance']);
diff --git a/src/Item/Field.php b/src/Item/Field.php
index bf09974..3942a24 100644
--- a/src/Item/Field.php
+++ b/src/Item/Field.php
@@ -640,7 +640,9 @@ public function __sleep() {
    * Implements the magic __wakeup() method to control object unserialization.
    */
   public function __wakeup() {
-    if ($this->indexId) {
+    // Make sure we have a container to do this. This is important to correctly
+    // display test failures.
+    if ($this->indexId && \Drupal::hasContainer()) {
       $this->index = Index::load($this->indexId);
       unset($this->indexId);
     }
diff --git a/tests/src/Unit/EntitySerializationTest.php b/tests/src/Kernel/EntitySerializationTest.php
similarity index 55%
rename from tests/src/Unit/EntitySerializationTest.php
rename to tests/src/Kernel/EntitySerializationTest.php
index cab8598..10d588a 100644
--- a/tests/src/Unit/EntitySerializationTest.php
+++ b/tests/src/Kernel/EntitySerializationTest.php
@@ -1,33 +1,29 @@
 <?php
 
-namespace Drupal\Tests\search_api\Unit;
+namespace Drupal\Tests\search_api\Kernel;
 
 use Drupal\Component\Serialization\Yaml;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\KernelTests\KernelTestBase;
 use Drupal\search_api\Entity\Index;
 use Drupal\search_api\Entity\Server;
-use Drupal\Tests\UnitTestCase;
 
 /**
  * Tests the serialization of the entities.
  *
  * @group search_api
  */
-class EntitySerializationTest extends UnitTestCase {
+class EntitySerializationTest extends KernelTestBase {
 
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
-    $config = $this->getMockBuilder('Drupal\Core\Config\Config')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $mock_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
-    $mock_factory->method('get')->willReturn($config);
-    $container = new ContainerBuilder();
-    $container->set('config.factory', $mock_factory);
-    \Drupal::setContainer($container);
-  }
+  public static $modules = array(
+    'search_api',
+    'search_api_test',
+    'node',
+    'user',
+    'system',
+  );
 
   /**
    * Tests that serialization of index entities doesn't lead to data loss.
@@ -38,10 +34,26 @@ public function testIndexSerialization() {
     $index_values = Yaml::decode(file_get_contents($path));
     $index = new Index($index_values, 'search_api_index');
 
+    // Make some changes to the index to ensure they're saved, too.
+    $field_helper = \Drupal::getContainer()->get('search_api.fields_helper');
+    $field_info = array(
+      'type' => 'date',
+      'datasource_id' => 'entity:node',
+      'property_path' => 'uid:entity:created',
+    );
+    $index->addField($field_helper->createField($index, 'test1', $field_info));
+    $index->addDatasource($index->createPlugin('datasource', 'entity:user'));
+    $index->addProcessor($index->createPlugin('processor', 'highlight'));
+    $index->setTracker($index->createPlugin('tracker', 'search_api_test'));
+
+    /** @var \Drupal\search_api\IndexInterface $serialized */
     $serialized = unserialize(serialize($index));
 
     $this->assertNotEmpty($serialized);
-    $this->assertEquals($index, $serialized);
+    $storage = \Drupal::entityTypeManager()->getStorage('search_api_index');
+    $index->preSave($storage);
+    $serialized->preSave($storage);
+    $this->assertEquals($index->toArray(), $serialized->toArray());
   }
 
   /**
