diff --git a/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.info.yml b/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.info.yml
new file mode 100644
index 0000000..aab3456
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Migrate source test'
+type: module
+description: 'Support module for source tests.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.module b/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.module
new file mode 100644
index 0000000..32be4e7
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_source_test/migrate_source_test.module
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+ * Contains migrate_source_test.module.
+ */
+
+use Drupal\Core\Database\Query\AlterableInterface;
+
+/**
+ * Implements hook_query_TAG_alter().
+ */
+function migrate_source_test_query_some_special_tag_alter(AlterableInterface $query) {
+  // Filter out one record to decrease the query count by 1.
+  $query->condition('name', 'baz', '<>');
+}
diff --git a/core/modules/migrate/tests/modules/migrate_source_test/src/Plugin/migrate/source/TestSqlSource.php b/core/modules/migrate/tests/modules/migrate_source_test/src/Plugin/migrate/source/TestSqlSource.php
new file mode 100644
index 0000000..5dbf61c
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_source_test/src/Plugin/migrate/source/TestSqlSource.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\migrate_source_test\Plugin\migrate\source;
+
+use Drupal\migrate\Plugin\migrate\source\SqlBase;
+
+/**
+ * Provides a testing source plugin based on SqlBase.
+ *
+ * @MigrateSource(
+ *   id = "test_sql_source"
+ * )
+ */
+class TestSqlSource extends SqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, \Drupal\migrate\Plugin\MigrationInterface $migration, \Drupal\Core\State\StateInterface $state) {
+    $configuration = ['key' => 'default', 'target' => 'default'];
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('migrate_source_test')->fields('migrate_source_test');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function prepareQuery() {
+    if (!$this->isQueryPrepared) {
+      $this->query = parent::prepareQuery();
+      // Add a custom tag to alter the query in hook_query_TAG_alter(). We check
+      // that count query gets altered too.
+      $this->query->addTag('some_special_tag');
+    }
+    return $this->query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    return ['id' => ['type' => 'integer']];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return ['id' => 'ID', 'name' => 'Name'];
+  }
+
+}
diff --git a/core/modules/migrate/tests/src/Kernel/SqlSourceTest.php b/core/modules/migrate/tests/src/Kernel/SqlSourceTest.php
new file mode 100644
index 0000000..c738dc4
--- /dev/null
+++ b/core/modules/migrate/tests/src/Kernel/SqlSourceTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\Tests\migrate\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+
+/**
+ * Tests query preparation in SqlBase source plugins.
+ *
+ * @group migrate
+ */
+class SqlSourceTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['migrate', 'migrate_source_test', 'entity_test'];
+
+  /**
+   * Tests query prepare.
+   */
+  public function testPrepareQuery() {
+    $this->createSourceTable();
+
+    /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
+    $migration = $this->container->get('plugin.manager.migration')
+      ->createStubMigration([
+        'source' => ['plugin' => 'test_sql_source'],
+        'process' => ['id' => 'id', 'name' => 'name'],
+        'destination' => ['plugin' => 'entity:entity_test'],
+      ]);
+
+    // Count source items using the SqlBase::count() method. We use this method
+    // before we run the migration to reflect the number of items to be
+    // migrated. After the migration run, this method would return only records
+    // that need update.
+    $count = $migration->getSourcePlugin()->count();
+
+    // Run the migration.
+    (new MigrateExecutable($migration, new MigrateMessage()))->import();
+
+    /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map */
+    $id_map = $migration->getIdMap();
+
+    // Check that counts are the same.
+    $this->assertEquals($count, $id_map->processedCount());
+  }
+
+  /**
+   * Creates a custom source table and some sample data.
+   */
+  protected function createSourceTable() {
+    /** @var \Drupal\Core\Database\Connection $db */
+    $db = $this->container->get('database');
+
+    // Create a custom source table and andd some sample data.
+    $db->schema()->createTable('migrate_source_test', ['fields' => [
+      'id' => ['type' => 'int'],
+      'name' => ['type' => 'varchar', 'length' => 32],
+    ]]);
+
+    $data = [
+      ['id' => 1, 'name' => 'foo'],
+      ['id' => 2, 'name' => 'bar'],
+      ['id' => 3, 'name' => 'baz'],
+    ];
+
+    // Add some data in the table.
+    $query = $db->insert('migrate_source_test')->fields(['id', 'name']);
+    foreach ($data as $row) {
+      $query->values($row);
+    }
+    $query->execute();
+  }
+
+}
