diff --git a/src/Operation/Explain.php b/src/Operation/Explain.php
index defbbf7ef9f89eed5b93e5b332e63644b8c360ba..5ba76bd1c2ad8f714fe659b7e7cc9d8c74124899 100644
--- a/src/Operation/Explain.php
+++ b/src/Operation/Explain.php
@@ -80,16 +80,12 @@ class Explain implements Executable
             throw UnsupportedException::explainNotSupported();
         }
 
-        if ($this->explainable instanceOf \MongoDB\Operation\Distinct) {
-            if (! \MongoDB\server_supports_feature($server, self::$wireVersionForDistinct)) {
-                throw UnsupportedException::explainNotSupported();
-            }
+        if ($this->explainable instanceof \MongoDB\Operation\Distinct && ! \MongoDB\server_supports_feature($server, self::$wireVersionForDistinct)) {
+            throw UnsupportedException::explainNotSupported();
         }
 
-        if ($this->explainable instanceOf \MongoDB\Operation\FindAndModify) {
-            if (! \MongoDB\server_supports_feature($server, self::$wireVersionForFindAndModify)) {
-                throw UnsupportedException::explainNotSupported();
-            }
+        if ($this->explainable instanceof \MongoDB\Operation\FindAndModify && ! \MongoDB\server_supports_feature($server, self::$wireVersionForFindAndModify)) {
+            throw UnsupportedException::explainNotSupported();
         }
 
         $cmd = ['explain' => $this->explainable->getCommandDocument()];
diff --git a/tests/Operation/ExplainFunctionalTest.php b/tests/Operation/ExplainFunctionalTest.php
index a593403717bf12486c12b6a4367c0995b0057da3..064765fa498bcc66c5f1f7fbd280f49fd956a61c 100644
--- a/tests/Operation/ExplainFunctionalTest.php
+++ b/tests/Operation/ExplainFunctionalTest.php
@@ -22,65 +22,10 @@ class ExplainFunctionalTest extends FunctionalTestCase
         }
     }
 
-    public function testCountAllPlansExecution()
-    {
-        $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
-            ['x' => 0],
-            ['x' => 1],
-            ['x' => 2],
-            ['y' => 3]
-        ]);
-        $insertMany->execute($this->getPrimaryServer());
-
-        $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testCountDefaultVerbosity()
-    {
-        $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
-            ['x' => 0],
-            ['x' => 1],
-            ['x' => 2],
-            ['y' => 3]
-        ]);
-        $insertMany->execute($this->getPrimaryServer());
-
-        $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testCountExecutionStats()
-    {
-        $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
-            ['x' => 0],
-            ['x' => 1],
-            ['x' => 2],
-            ['y' => 3]
-        ]);
-        $insertMany->execute($this->getPrimaryServer());
-
-        $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-
-        $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testCountQueryPlanner()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testCount($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
             ['x' => 0],
@@ -91,62 +36,16 @@ class ExplainFunctionalTest extends FunctionalTestCase
         $insertMany->execute($this->getPrimaryServer());
 
         $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertFalse(array_key_exists('executionStats', $result));
-    }
-
-    public function testDistinctAllPlansExecution()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
-        }
-
-        $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testDistinctDefaultVerbosity()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
-        }
-
-        $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testDistinctExecutionStats()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
-        }
-
-        $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testDistinctQueryPlanner()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testDistinct($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
             $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
@@ -154,62 +53,16 @@ class ExplainFunctionalTest extends FunctionalTestCase
 
         $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
 
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertFalse(array_key_exists('executionStats', $result));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testFindAndModifyAllPlansExecution()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
-        }
-
-        $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindAndModifyDefaultVerbosity()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
-        }
-
-        $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindAndModifyExecutionStats()
-    {
-        if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
-            $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
-        }
-
-        $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindAndModifyQueryPlanner()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testFindAndModify($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
             $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
@@ -217,69 +70,31 @@ class ExplainFunctionalTest extends FunctionalTestCase
 
         $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
 
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertFalse(array_key_exists('executionStats', $result));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testFindAllPlansExecution()
-    {
-        $this->createFixtures(3);
-
-        $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindDefaultVerbosity()
-    {
-        $this->createFixtures(3);
-
-        $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindExecutionStats()
-    {
-        $this->createFixtures(3);
-
-        $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindQueryPlanner()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testFind($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         $this->createFixtures(3);
 
         $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
 
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertFalse(array_key_exists('executionStats', $result));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testFindMaxAwait()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testFindMaxAwait($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
             $this->markTestSkipped('maxAwaitTimeMS option is not supported');
@@ -312,67 +127,49 @@ class ExplainFunctionalTest extends FunctionalTestCase
 
         $operation = new Find($databaseName, $cappedCollectionName, [], ['cursorType' => Find::TAILABLE_AWAIT, 'maxAwaitTimeMS' => $maxAwaitTimeMS]);
 
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
-    }
-
-    public function testFindOneAllPlansExecution()
-    {
-        $this->createFixtures(1);
-
-        $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testFindOneDefaultVerbosity()
+    /**
+     * @dataProvider provideVerbosityInformation
+     */
+    public function testFindOne($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
     {
         $this->createFixtures(1);
 
         $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
 
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
+        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
         $result = $explainOperation->execute($this->getPrimaryServer());
 
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+        $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
     }
 
-    public function testFindOneExecutionStats()
+    public function provideVerbosityInformation()
     {
-        $this->createFixtures(1);
-
-        $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertTrue(array_key_exists('executionStats', $result));
-        $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
+        return [
+            [Explain::VERBOSITY_ALL_PLANS, true, true],
+            [Explain::VERBOSITY_EXEC_STATS, true, false],
+            [Explain::VERBOSITY_QUERY, false, false]
+        ];
     }
 
-    public function testFindOneQueryPlanner()
+    private function assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected)
     {
-        $this->createFixtures(1);
-
-        $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
-        $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
-        $result = $explainOperation->execute($this->getPrimaryServer());
-
-        $this->assertTrue(array_key_exists('queryPlanner', $result));
-        $this->assertFalse(array_key_exists('executionStats', $result));
+        $this->assertArrayHasKey('queryPlanner', $result);
+        if ($executionStatsExpected) {
+            $this->assertArrayHasKey('executionStats', $result);
+            if ($allPlansExecutionExpected) {
+                $this->assertArrayHasKey('allPlansExecution', $result['executionStats']);
+            } else {
+                $this->assertArrayNotHasKey('allPlansExecution', $result['executionStats']);
+            }
+        } else {
+            $this->assertArrayNotHasKey('executionStats', $result);
+        }
     }
 
     /**
diff --git a/tests/Operation/ExplainTest.php b/tests/Operation/ExplainTest.php
index 1372affc7f99bd3cb91888b8ab166564bf436b16..6711e887fd620ec5e041e3ab91ca53fb7538aabf 100644
--- a/tests/Operation/ExplainTest.php
+++ b/tests/Operation/ExplainTest.php
@@ -12,19 +12,9 @@ class ExplainTest extends TestCase
      * @expectedException MongoDB\Exception\InvalidArgumentException
      * @dataProvider provideInvalidConstructorOptions
      */
-    public function testConstructorOptionTypeChecksForCount(array $options)
+    public function testConstructorOptionTypeChecks(array $options)
     {
-        $explainable = new Count($this->getDatabaseName(), $this->getCollectionName(),[]);
-        new Explain($this->getDatabaseName(), $explainable, $options);
-    }
-
-    /**
-     * @expectedException MongoDB\Exception\InvalidArgumentException
-     * @dataProvider provideInvalidConstructorOptions
-     */
-    public function testConstructorOptionTypeChecksForDistinct(array $options)
-    {
-        $explainable = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
+        $explainable = $this->createMock('MongoDB\Operation\Explainable');
         new Explain($this->getDatabaseName(), $explainable, $options);
     }