diff --git a/lib/Drupal/views/Tests/Plugin/QueryTest.php b/lib/Drupal/views/Tests/Plugin/QueryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ba11246689ae48e155d36ae37dab0019177a73b
--- /dev/null
+++ b/lib/Drupal/views/Tests/Plugin/QueryTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\Tests\Plugin\QueryTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\views\Tests\ViewTestBase;
+use Drupal\views_test_data\Plugin\views\query\QueryTest as QueryTestPlugin;
+
+/**
+ * Tests query plugins.
+ */
+class QueryTest extends ViewTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Query',
+      'description' => 'Tests query plugins.',
+      'group' => 'Views Plugins'
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    $this->enableViewsTestModule();
+  }
+
+  protected function viewsData() {
+    $data = parent::viewsData();
+    $data['views_test_data']['table']['base']['query_id'] = 'query_test';
+
+    return $data;
+  }
+
+  /**
+   * Tests query plugins.
+   */
+  public function testQuery() {
+    $this->_testInitQuery();
+    $this->_testQueryExecute();
+  }
+
+  /**
+   * Tests the ViewExecutable::initQuery method.
+   */
+  public function _testInitQuery() {
+    $view = $this->getBasicView();
+    $view->initQuery();
+    $this->assertTrue($view->query instanceof QueryTestPlugin, 'Make sure the right query plugin got instantiated.');
+  }
+
+  public function _testQueryExecute() {
+    $view = $this->getBasicView();
+    $view->initQuery();
+    $view->query->setAllItems($this->dataSet());
+
+    $this->executeView($view);
+    $this->assertTrue($view->result, 'Make sure the view result got filled');
+  }
+
+}
diff --git a/lib/Drupal/views/ViewExecutable.php b/lib/Drupal/views/ViewExecutable.php
index f3abf4466b4f65afccfd0ff9be1099c97318419a..36aaee80ab9014aed4528e82b23df93ddce4019f 100644
--- a/lib/Drupal/views/ViewExecutable.php
+++ b/lib/Drupal/views/ViewExecutable.php
@@ -947,7 +947,7 @@ public function initQuery() {
     $query_options = $this->display_handler->getOption('query');
 
     // Create and initialize the query object.
-    $plugin = !empty($views_data['table']['base']['query class']) ? $views_data['table']['base']['query class'] : 'views_query';
+    $plugin = !empty($views_data['table']['base']['query_id']) ? $views_data['table']['base']['query_id'] : 'views_query';
     $this->query = views_get_plugin('query', $plugin);
 
     if (empty($this->query)) {
diff --git a/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/join/JoinTest.php b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/join/JoinTest.php
index 35d0959e4c6c3accc08eb18605b29b5730fd8c68..5d0cb73d127596802bb8dfc7fa37428211db111d 100644
--- a/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/join/JoinTest.php
+++ b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/join/JoinTest.php
@@ -12,7 +12,7 @@
 use Drupal\Core\Annotation\Translation;
 
 /**
- * Defines a Display test plugin.
+ * Defines a join test plugin.
  *
  * @Plugin(
  *   id = "join_test",
diff --git a/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/query/QueryTest.php b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/query/QueryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..eab54df0fca2734c8354b5b1b0013be8f269bf19
--- /dev/null
+++ b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/query/QueryTest.php
@@ -0,0 +1,127 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views_test_data\Plugin\views\query\QueryTest.
+ */
+
+namespace Drupal\views_test_data\Plugin\views\query;
+
+use Drupal\views\Plugin\views\query\QueryPluginBase;
+use Drupal\views\Plugin\views\join\JoinPluginBase;
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines a query test plugin.
+ *
+ * @Plugin(
+ *   id = "query_test",
+ *   title = @Translation("Query test")
+ * )
+ */
+class QueryTest extends QueryPluginBase {
+  protected $conditions = array();
+  protected $fields = array();
+  protected $allItems = array();
+  protected $orderBy = array();
+
+  /**
+   * Sets the allItems property.
+   *
+   * @param array $allItems
+   *   An array of stdClasses.
+   */
+  public function setAllItems($allItems) {
+    $this->allItems = $allItems;
+  }
+
+  public function add_where($group, $field, $value = NULL, $operator = NULL) {
+    $this->conditions[] = array(
+      'field' => $field,
+      'value' => $value,
+      'operator' => $operator
+    );
+
+  }
+
+  public function add_field($table, $field, $alias = '', $params = array()) {
+    $this->fields[$field] = $field;
+    return $field;
+  }
+
+  public function add_orderby($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) {
+    $this->orderBy = array('field' => $field, 'order' => $order);
+  }
+
+
+  public function ensure_table($table, $relationship = NULL, JoinPluginBase $join = NULL) {
+    // There is no concept of joins.
+  }
+
+  /**
+   * Implements Drupal\views\Plugin\views\query\QueryPluginBase::build().
+   *
+   * @param Drupal\views\ViewExecutable $view
+   */
+  public function build(ViewExecutable $view) {
+    $this->view = $view;
+    // @todo Support pagers for know, a php based one would probably match.
+    // @todo You could add a string representatin of the query.
+    $this->view->build_info['query'] = "";
+    $this->view->build_info['count_query'] = "";
+}
+
+  /**
+   * Implements Drupal\views\Plugin\views\query\QueryPluginBase::execute().
+   */
+  public function execute(ViewExecutable $view) {
+    $result = array();
+    foreach ($this->allItems as $element) {
+      // Run all conditions on the element, and add it to the result if they
+      // match.
+      $match = TRUE;
+      foreach ($this->conditions as $condition) {
+        $match &= $this->match($element, $condition);
+      }
+      if ($match) {
+        // If the query explicit defines fields to use, filter all others out.
+        // Filter out fields
+        if ($this->fields) {
+          $element = array_intersect_key($element, $this->fields);
+        }
+        $result[] = (object) $element;
+      }
+    }
+    $this->view->result = $result;
+  }
+
+  /**
+   * Check a single condition for a single element.
+   *
+   * @param array $element
+   *   The element which should be checked.
+   * @param array $condition
+   *   An associative array containing:
+   *   - field: The field to by, for example id.
+   *   - value: The expected value of the element.
+   *   - operator: The operator to compare the element value with the expected
+   *     value.
+   *
+   * @return bool
+   *   Returns whether the condition matches with the element.
+   */
+  public function match($element, $condition) {
+    $value = $element[$condition['field']];
+    switch ($condition['operator']) {
+      case '=':
+        return $value == $condition['value'];
+      case 'IN':
+        return in_array($value, $condition['value']);
+    }
+    return FALSE;
+  }
+
+
+}