From 529af8edc48c7f2e852df45118f681b8dc0a991b Mon Sep 17 00:00:00 2001
From: Klimov Paul <klimov.paul@gmail.com>
Date: Tue, 26 Nov 2013 21:16:55 +0200
Subject: [PATCH] Mongo "Database" and "Collection" classes introduced.

---
 extensions/mongo/Collection.php                | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 extensions/mongo/Command.php                   | 159 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
 extensions/mongo/Connection.php                | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------
 extensions/mongo/Database.php                  |  64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/unit/extensions/mongo/CollectionTest.php |  96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/unit/extensions/mongo/CommandTest.php    |  96 ------------------------------------------------------------------------------------------------
 tests/unit/extensions/mongo/ConnectionTest.php |  58 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 tests/unit/extensions/mongo/DatabaseTest.php   |  34 ++++++++++++++++++++++++++++++++++
 tests/unit/extensions/mongo/MongoTestCase.php  |   6 +++---
 9 files changed, 469 insertions(+), 318 deletions(-)
 create mode 100644 extensions/mongo/Collection.php
 delete mode 100644 extensions/mongo/Command.php
 create mode 100644 extensions/mongo/Database.php
 create mode 100644 tests/unit/extensions/mongo/CollectionTest.php
 delete mode 100644 tests/unit/extensions/mongo/CommandTest.php
 create mode 100644 tests/unit/extensions/mongo/DatabaseTest.php

diff --git a/extensions/mongo/Collection.php b/extensions/mongo/Collection.php
new file mode 100644
index 0000000..fc15b89
--- /dev/null
+++ b/extensions/mongo/Collection.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\mongo;
+
+use yii\base\Object;
+use Yii;
+
+/**
+ * Collection represents the Mongo collection information.
+ *
+ * @author Paul Klimov <klimov.paul@gmail.com>
+ * @since 2.0
+ */
+class Collection extends Object
+{
+	/**
+	 * @var \MongoCollection Mongo collection instance.
+	 */
+	public $mongoCollection;
+
+	/**
+	 * Drops this collection.
+	 */
+	public function drop()
+	{
+		$this->mongoCollection->drop();
+	}
+
+	/**
+	 * @param array $query
+	 * @param array $fields
+	 * @return \MongoCursor
+	 */
+	public function find($query = [], $fields = [])
+	{
+		return $this->mongoCollection->find($query, $fields);
+	}
+
+	/**
+	 * @param array $query
+	 * @param array $fields
+	 * @return array
+	 */
+	public function findAll($query = [], $fields = [])
+	{
+		$cursor = $this->find($query, $fields);
+		$result = [];
+		foreach ($cursor as $data) {
+			$result[] = $data;
+		}
+		return $result;
+	}
+
+	/**
+	 * Inserts new data into collection.
+	 * @param array|object $data data to be inserted.
+	 * @param array $options list of options in format: optionName => optionValue.
+	 * @return \MongoId new record id instance.
+	 * @throws Exception on failure.
+	 */
+	public function insert($data, $options = [])
+	{
+		$token = 'Inserting data into ' . $this->mongoCollection->getName();
+		Yii::info($token, __METHOD__);
+		try {
+			Yii::beginProfile($token, __METHOD__);
+			$this->tryResultError($this->mongoCollection->insert($data, $options));
+			Yii::endProfile($token, __METHOD__);
+			return is_array($data) ? $data['_id'] : $data->_id;
+		} catch (\Exception $e) {
+			Yii::endProfile($token, __METHOD__);
+			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
+		}
+	}
+
+	/**
+	 * Update the existing database data, otherwise insert this data
+	 * @param array|object $data data to be updated/inserted.
+	 * @param array $options list of options in format: optionName => optionValue.
+	 * @return \MongoId updated/new record id instance.
+	 * @throws Exception on failure.
+	 */
+	public function save($data, $options = [])
+	{
+		$token = 'Saving data into ' . $this->mongoCollection->getName();
+		Yii::info($token, __METHOD__);
+		try {
+			Yii::beginProfile($token, __METHOD__);
+			$this->tryResultError($this->mongoCollection->save($data, $options));
+			Yii::endProfile($token, __METHOD__);
+			return is_array($data) ? $data['_id'] : $data->_id;
+		} catch (\Exception $e) {
+			Yii::endProfile($token, __METHOD__);
+			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
+		}
+	}
+
+	/**
+	 * Removes data from the collection.
+	 * @param array $criteria description of records to remove.
+	 * @param array $options list of options in format: optionName => optionValue.
+	 * @return boolean whether operation was successful.
+	 * @throws Exception on failure.
+	 */
+	public function remove($criteria = [], $options = [])
+	{
+		$token = 'Removing data from ' . $this->mongoCollection->getName();
+		Yii::info($token, __METHOD__);
+		try {
+			Yii::beginProfile($token, __METHOD__);
+			$this->tryResultError($this->mongoCollection->remove($criteria, $options));
+			Yii::endProfile($token, __METHOD__);
+			return true;
+		} catch (\Exception $e) {
+			Yii::endProfile($token, __METHOD__);
+			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
+		}
+	}
+
+	/**
+	 * Checks if command execution result ended with an error.
+	 * @param mixed $result raw command execution result.
+	 * @throws Exception if an error occurred.
+	 */
+	protected function tryResultError($result)
+	{
+		if (is_array($result)) {
+			if (!empty($result['err'])) {
+				throw new Exception($result['errmsg'], (int)$result['code']);
+			}
+		} elseif (!$result) {
+			throw new Exception('Unknown error, use "w=1" option to enable error tracking');
+		}
+	}
+}
\ No newline at end of file
diff --git a/extensions/mongo/Command.php b/extensions/mongo/Command.php
deleted file mode 100644
index 7a21177..0000000
--- a/extensions/mongo/Command.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-/**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
-
-namespace yii\mongo;
-
-use \yii\base\Component;
-use Yii;
-
-/**
- * Class Command
- *
- * @author Paul Klimov <klimov.paul@gmail.com>
- * @since 2.0
- */
-class Command extends Component
-{
-	/**
-	 * @var Connection the Mongo connection that this command is associated with
-	 */
-	public $db;
-
-	/**
-	 * Drops the current database
-	 */
-	public function dropDb()
-	{
-		$this->db->db->drop();
-	}
-
-	/**
-	 * Drops the specified collection.
-	 * @param string $name collection name.
-	 */
-	public function dropCollection($name)
-	{
-		$collection = $this->db->getCollection($name);
-		$collection->drop();
-	}
-
-	/**
-	 * @param $collection
-	 * @param array $query
-	 * @param array $fields
-	 * @return \MongoCursor
-	 */
-	public function find($collection, $query = [], $fields = [])
-	{
-		$collection = $this->db->getCollection($collection);
-		return $collection->find($query, $fields);
-	}
-
-	/**
-	 * @param $collection
-	 * @param array $query
-	 * @param array $fields
-	 * @return array
-	 */
-	public function findAll($collection, $query = [], $fields = [])
-	{
-		$cursor = $this->find($collection, $query, $fields);
-		$result = [];
-		foreach ($cursor as $data) {
-			$result[] = $data;
-		}
-		return $result;
-	}
-
-	/**
-	 * Inserts new data into collection.
-	 * @param string $collection name of the collection.
-	 * @param array|object $data data to be inserted.
-	 * @param array $options list of options in format: optionName => optionValue.
-	 * @return \MongoId new record id instance.
-	 * @throws Exception on failure.
-	 */
-	public function insert($collection, $data, $options = [])
-	{
-		$token = 'Inserting data into ' . $collection;
-		Yii::info($token, __METHOD__);
-		try {
-			Yii::beginProfile($token, __METHOD__);
-			$collection = $this->db->getCollection($collection);
-			$this->tryResultError($collection->insert($data, $options));
-			Yii::endProfile($token, __METHOD__);
-			return is_array($data) ? $data['_id'] : $data->_id;
-		} catch (\Exception $e) {
-			Yii::endProfile($token, __METHOD__);
-			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
-		}
-	}
-
-	/**
-	 * Update the existing database data, otherwise insert this data
-	 * @param string $collection name of the collection.
-	 * @param array|object $data data to be updated/inserted.
-	 * @param array $options list of options in format: optionName => optionValue.
-	 * @return \MongoId updated/new record id instance.
-	 * @throws Exception on failure.
-	 */
-	public function save($collection, $data, $options = [])
-	{
-		$token = 'Saving data into ' . $collection;
-		Yii::info($token, __METHOD__);
-		try {
-			Yii::beginProfile($token, __METHOD__);
-			$collection = $this->db->getCollection($collection);
-			$this->tryResultError($collection->save($data, $options));
-			Yii::endProfile($token, __METHOD__);
-			return is_array($data) ? $data['_id'] : $data->_id;
-		} catch (\Exception $e) {
-			Yii::endProfile($token, __METHOD__);
-			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
-		}
-	}
-
-	/**
-	 * Removes data from the collection.
-	 * @param string $collection name of the collection.
-	 * @param array $criteria description of records to remove.
-	 * @param array $options list of options in format: optionName => optionValue.
-	 * @return boolean whether operation was successful.
-	 * @throws Exception on failure.
-	 */
-	public function remove($collection, $criteria = [], $options = [])
-	{
-		$token = 'Removing data from ' . $collection;
-		Yii::info($token, __METHOD__);
-		try {
-			Yii::beginProfile($token, __METHOD__);
-			$collection = $this->db->getCollection($collection);
-			$this->tryResultError($collection->remove($criteria, $options));
-			Yii::endProfile($token, __METHOD__);
-			return true;
-		} catch (\Exception $e) {
-			Yii::endProfile($token, __METHOD__);
-			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
-		}
-	}
-
-	/**
-	 * Checks if command execution result ended with an error.
-	 * @param mixed $result raw command execution result.
-	 * @throws Exception if an error occurred.
-	 */
-	protected function tryResultError($result)
-	{
-		if (is_array($result)) {
-			if (!empty($result['err'])) {
-				throw new Exception($result['errmsg'], (int)$result['code']);
-			}
-		} elseif (!$result) {
-			throw new Exception('Unknown error, use "w=1" option to enable error tracking');
-		}
-	}
-}
\ No newline at end of file
diff --git a/extensions/mongo/Connection.php b/extensions/mongo/Connection.php
index 8158b15..ce99ee4 100644
--- a/extensions/mongo/Connection.php
+++ b/extensions/mongo/Connection.php
@@ -24,14 +24,16 @@ use Yii;
 class Connection extends Component
 {
 	/**
-	 * @var \MongoCollection[] list of Mongo collection available in database.
-	 */
-	private $_collections = [];
-
-	/**
-	 * @var \MongoClient mongo client instance.
+	 * @var string host:port
+	 *
+	 * Correct syntax is:
+	 * mongodb://[username:password@]host1[:port1][,host2[:port2:],...][/dbname]
+	 * For example:
+	 * mongodb://localhost:27017
+	 * mongodb://developer:somepassword@localhost:27017
+	 * mongodb://developer:somepassword@localhost:27017/mydatabase
 	 */
-	public $client;
+	public $dsn;
 	/**
 	 * @var array connection options.
 	 * for example:
@@ -45,34 +47,83 @@ class Connection extends Component
 	 */
 	public $options = [];
 	/**
-	 * @var string host:port
-	 *
-	 * Correct syntax is:
-	 * mongodb://[username:password@]host1[:port1][,host2[:port2:],...]
-	 * For example: mongodb://localhost:27017
+	 * @var string name of the Mongo database to use by default.
 	 */
-	public $dsn;
+	public $defaultDatabaseName;
+	/**
+	 * @var \MongoClient mongo client instance.
+	 */
+	public $mongoClient;
+	/**
+	 * @var Database[] list of Mongo databases
+	 */
+	private $_databases = [];
+
+	/**
+	 * Returns the Mongo collection with the given name.
+	 * @param string|null $name collection name, if null default one will be used.
+	 * @param boolean $refresh whether to reload the table schema even if it is found in the cache.
+	 * @return Database database instance.
+	 */
+	public function getDatabase($name = null, $refresh = false)
+	{
+		if ($name === null) {
+			$name = $this->fetchDefaultDatabaseName();
+		}
+		if ($refresh || !array_key_exists($name, $this->_databases)) {
+			$this->_databases[$name] = $this->selectDatabase($name);
+		}
+		return $this->_databases[$name];
+	}
+
 	/**
-	 * @var string name of the Mongo database to use
+	 * Returns [[defaultDatabaseName]] value, if it is not set,
+	 * attempts to determine it from [[dsn]] value.
+	 * @return string default database name
+	 * @throws \yii\base\InvalidConfigException if unable to determine default database name.
 	 */
-	public $dbName;
+	protected function fetchDefaultDatabaseName()
+	{
+		if ($this->defaultDatabaseName === null) {
+			if (preg_match('/^mongodb:\\/\\/.+\\/(.+)$/s', $this->dsn, $matches)) {
+				$this->defaultDatabaseName = $matches[1];
+			} else {
+				throw new InvalidConfigException("Unable to determine default database name from dsn.");
+			}
+		}
+		return $this->defaultDatabaseName;
+	}
+
 	/**
-	 * @var \MongoDb Mongo database instance.
+	 * Selects the database with given name.
+	 * @param string $name database name.
+	 * @return Database database instance.
 	 */
-	public $db;
+	protected function selectDatabase($name)
+	{
+		$this->open();
+		return Yii::createObject([
+			'class' => 'yii\mongo\Database',
+			'mongoDb' => $this->mongoClient->selectDB($name)
+		]);
+	}
 
 	/**
 	 * Returns the Mongo collection with the given name.
-	 * @param string $name collection name
+	 * @param string|array $name collection name. If string considered as  the name of the collection
+	 * inside the default database. If array - first element considered as the name of the database,
+	 * second - as name of collection inside that database
 	 * @param boolean $refresh whether to reload the table schema even if it is found in the cache.
-	 * @return \MongoCollection mongo collection instance.
+	 * @return Collection Mongo collection instance.
 	 */
 	public function getCollection($name, $refresh = false)
 	{
-		if ($refresh || !array_key_exists($name, $this->_collections)) {
-			$this->_collections[$name] = $this->client->selectCollection($this->dbName, $name);
+		if (is_array($name)) {
+			list ($dbName, $collectionName) = $name;
+			return $this->getDatabase($dbName)->getCollection($collectionName, $refresh);
+		} else {
+			return $this->getDatabase()->getCollection($name, $refresh);
 		}
-		return $this->_collections[$name];
 	}
 
 	/**
@@ -81,7 +132,7 @@ class Connection extends Component
 	 */
 	public function getIsActive()
 	{
-		return is_object($this->client) && $this->client->connected;
+		return is_object($this->mongoClient) && $this->mongoClient->connected;
 	}
 
 	/**
@@ -91,7 +142,7 @@ class Connection extends Component
 	 */
 	public function open()
 	{
-		if ($this->client === null) {
+		if ($this->mongoClient === null) {
 			if (empty($this->dsn)) {
 				throw new InvalidConfigException($this->className() . '::dsn cannot be empty.');
 			}
@@ -101,9 +152,10 @@ class Connection extends Component
 				Yii::beginProfile($token, __METHOD__);
 				$options = $this->options;
 				$options['connect'] = true;
-				$options['db'] = $this->dbName;
-				$this->client = new \MongoClient($this->dsn, $options);
-				$this->db = $this->client->selectDB($this->dbName);
+				if ($this->defaultDatabaseName !== null) {
+					$options['db'] = $this->defaultDatabaseName;
+				}
+				$this->mongoClient = new \MongoClient($this->dsn, $options);
 				Yii::endProfile($token, __METHOD__);
 			} catch (\Exception $e) {
 				Yii::endProfile($token, __METHOD__);
@@ -118,32 +170,10 @@ class Connection extends Component
 	 */
 	public function close()
 	{
-		if ($this->client !== null) {
+		if ($this->mongoClient !== null) {
 			Yii::trace('Closing Mongo connection: ' . $this->dsn, __METHOD__);
-			$this->client = null;
-			$this->db = null;
+			$this->mongoClient = null;
+			$this->_databases = [];
 		}
 	}
-
-	/**
-	 * Returns the query builder for the current DB connection.
-	 * @return QueryBuilder the query builder for the current DB connection.
-	 */
-	public function getQueryBuilder()
-	{
-		return new QueryBuilder($this);
-	}
-
-	/**
-	 * Creates a command for execution.
-	 * @return Command the Mongo command
-	 */
-	public function createCommand()
-	{
-		$this->open();
-		$command = new Command([
-			'db' => $this,
-		]);
-		return $command;
-	}
 }
\ No newline at end of file
diff --git a/extensions/mongo/Database.php b/extensions/mongo/Database.php
new file mode 100644
index 0000000..4954a20
--- /dev/null
+++ b/extensions/mongo/Database.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\mongo;
+
+use yii\base\Object;
+use Yii;
+
+/**
+ * Database represents the Mongo database information.
+ *
+ * @author Paul Klimov <klimov.paul@gmail.com>
+ * @since 2.0
+ */
+class Database extends Object
+{
+	/**
+	 * @var \MongoDB Mongo database instance.
+	 */
+	public $mongoDb;
+	/**
+	 * @var Collection[] list of collections.
+	 */
+	private $_collections = [];
+
+	/**
+	 * Returns the Mongo collection with the given name.
+	 * @param string $name collection name
+	 * @param boolean $refresh whether to reload the table schema even if it is found in the cache.
+	 * @return Collection mongo collection instance.
+	 */
+	public function getCollection($name, $refresh = false)
+	{
+		if ($refresh || !array_key_exists($name, $this->_collections)) {
+			$this->_collections[$name] = $this->selectCollection($name);
+		}
+		return $this->_collections[$name];
+	}
+
+	/**
+	 * Selects collection with given name.
+	 * @param string $name collection name.
+	 * @return Collection collection instance.
+	 */
+	protected function selectCollection($name)
+	{
+		return Yii::createObject([
+			'class' => 'yii\mongo\Collection',
+			'mongoCollection' => $this->mongoDb->selectCollection($name)
+		]);
+	}
+
+	/**
+	 * Drops this database.
+	 */
+	public function drop()
+	{
+		$this->mongoDb->drop();
+	}
+}
\ No newline at end of file
diff --git a/tests/unit/extensions/mongo/CollectionTest.php b/tests/unit/extensions/mongo/CollectionTest.php
new file mode 100644
index 0000000..5dd7d59
--- /dev/null
+++ b/tests/unit/extensions/mongo/CollectionTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace yiiunit\extensions\mongo;
+
+/**
+ * @group mongo
+ */
+class CollectionTest extends MongoTestCase
+{
+	protected function tearDown()
+	{
+		$this->dropCollection('customer');
+		parent::tearDown();
+	}
+
+	// Tests :
+
+	public function testInsert()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+		];
+		$id = $collection->insert($data);
+		$this->assertTrue($id instanceof \MongoId);
+		$this->assertNotEmpty($id->__toString());
+	}
+
+	/**
+	 * @depends testInsert
+	 */
+	public function testFindAll()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+		];
+		$id = $collection->insert($data);
+
+		$rows = $collection->findAll();
+		$this->assertEquals(1, count($rows));
+		$this->assertEquals($id, $rows[0]['_id']);
+	}
+
+	public function testSave()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+		];
+		$id = $collection->save($data);
+		$this->assertTrue($id instanceof \MongoId);
+		$this->assertNotEmpty($id->__toString());
+	}
+
+	/**
+	 * @depends testSave
+	 */
+	public function testUpdate()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+		];
+		$newId = $collection->save($data);
+
+		$updatedId = $collection->save($data);
+		$this->assertEquals($newId, $updatedId, 'Unable to update data!');
+
+		$data['_id'] = $newId->__toString();
+		$updatedId = $collection->save($data);
+		$this->assertEquals($newId, $updatedId, 'Unable to updated data by string id!');
+	}
+
+	/**
+	 * @depends testFindAll
+	 */
+	public function testRemove()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+		];
+		$id = $collection->insert($data);
+
+		$collection->remove(['_id' => $id]);
+
+		$rows = $collection->findAll();
+		$this->assertEquals(0, count($rows));
+	}
+}
\ No newline at end of file
diff --git a/tests/unit/extensions/mongo/CommandTest.php b/tests/unit/extensions/mongo/CommandTest.php
deleted file mode 100644
index c9621d1..0000000
--- a/tests/unit/extensions/mongo/CommandTest.php
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-
-namespace yiiunit\extensions\mongo;
-
-/**
- * @group mongo
- */
-class CommandTest extends MongoTestCase
-{
-	protected function tearDown()
-	{
-		$this->dropCollection('customer');
-		parent::tearDown();
-	}
-
-	// Tests :
-
-	public function testInsert()
-	{
-		$command = $this->getConnection()->createCommand();
-		$data = [
-			'name' => 'customer 1',
-			'address' => 'customer 1 address',
-		];
-		$id = $command->insert('customer', $data);
-		$this->assertTrue($id instanceof \MongoId);
-		$this->assertNotEmpty($id->__toString());
-	}
-
-	/**
-	 * @depends testInsert
-	 */
-	public function testFindAll()
-	{
-		$command = $this->getConnection()->createCommand();
-		$data = [
-			'name' => 'customer 1',
-			'address' => 'customer 1 address',
-		];
-		$id = $command->insert('customer', $data);
-
-		$rows = $command->findAll('customer');
-		$this->assertEquals(1, count($rows));
-		$this->assertEquals($id, $rows[0]['_id']);
-	}
-
-	public function testSave()
-	{
-		$command = $this->getConnection()->createCommand();
-		$data = [
-			'name' => 'customer 1',
-			'address' => 'customer 1 address',
-		];
-		$id = $command->save('customer', $data);
-		$this->assertTrue($id instanceof \MongoId);
-		$this->assertNotEmpty($id->__toString());
-	}
-
-	/**
-	 * @depends testSave
-	 */
-	public function testUpdate()
-	{
-		$command = $this->getConnection()->createCommand();
-		$data = [
-			'name' => 'customer 1',
-			'address' => 'customer 1 address',
-		];
-		$newId = $command->save('customer', $data);
-
-		$updatedId = $command->save('customer', $data);
-		$this->assertEquals($newId, $updatedId, 'Unable to update data!');
-
-		$data['_id'] = $newId->__toString();
-		$updatedId = $command->save('customer', $data);
-		$this->assertEquals($newId, $updatedId, 'Unable to updated data by string id!');
-	}
-
-	/**
-	 * @depends testFindAll
-	 */
-	public function testRemove()
-	{
-		$command = $this->getConnection()->createCommand();
-		$data = [
-			'name' => 'customer 1',
-			'address' => 'customer 1 address',
-		];
-		$id = $command->insert('customer', $data);
-
-		$command->remove('customer', ['_id' => $id]);
-
-		$rows = $command->findAll('customer');
-		$this->assertEquals(0, count($rows));
-	}
-}
\ No newline at end of file
diff --git a/tests/unit/extensions/mongo/ConnectionTest.php b/tests/unit/extensions/mongo/ConnectionTest.php
index 175a665..3b8a1a2 100644
--- a/tests/unit/extensions/mongo/ConnectionTest.php
+++ b/tests/unit/extensions/mongo/ConnectionTest.php
@@ -2,7 +2,9 @@
 
 namespace yiiunit\extensions\mongo;
 
+use yii\mongo\Collection;
 use yii\mongo\Connection;
+use yii\mongo\Database;
 
 /**
  * @group mongo
@@ -17,7 +19,7 @@ class ConnectionTest extends MongoTestCase
 		$connection->open();
 
 		$this->assertEquals($params['dsn'], $connection->dsn);
-		$this->assertEquals($params['dbName'], $connection->dbName);
+		$this->assertEquals($params['defaultDatabaseName'], $connection->defaultDatabaseName);
 		$this->assertEquals($params['options'], $connection->options);
 	}
 
@@ -26,17 +28,15 @@ class ConnectionTest extends MongoTestCase
 		$connection = $this->getConnection(false, false);
 
 		$this->assertFalse($connection->isActive);
-		$this->assertEquals(null, $connection->client);
+		$this->assertEquals(null, $connection->mongoClient);
 
 		$connection->open();
 		$this->assertTrue($connection->isActive);
-		$this->assertTrue(is_object($connection->client));
-		$this->assertTrue(is_object($connection->db));
+		$this->assertTrue(is_object($connection->mongoClient));
 
 		$connection->close();
 		$this->assertFalse($connection->isActive);
-		$this->assertEquals(null, $connection->client);
-		$this->assertEquals(null, $connection->db);
+		$this->assertEquals(null, $connection->mongoClient);
 
 		$connection = new Connection;
 		$connection->dsn = 'unknown::memory:';
@@ -44,10 +44,52 @@ class ConnectionTest extends MongoTestCase
 		$connection->open();
 	}
 
+	public function testGetDatabase()
+	{
+		$connection = $this->getConnection();
+
+		$database = $connection->getDatabase($connection->defaultDatabaseName);
+		$this->assertTrue($database instanceof Database);
+		$this->assertTrue($database->mongoDb instanceof \MongoDB);
+
+		$database2 = $connection->getDatabase($connection->defaultDatabaseName);
+		$this->assertTrue($database === $database2);
+
+		$databaseRefreshed = $connection->getDatabase($connection->defaultDatabaseName, true);
+		$this->assertFalse($database === $databaseRefreshed);
+	}
+
+	/**
+	 * @depends testGetDatabase
+	 */
+	public function testGetDefaultDatabase()
+	{
+		$connection = new Connection();
+		$connection->dsn = $this->mongoConfig['dsn'];
+		$connection->defaultDatabaseName = $this->mongoConfig['defaultDatabaseName'];
+		$database = $connection->getDatabase();
+		$this->assertTrue($database instanceof Database, 'Unable to get default database!');
+
+		$connection = new Connection();
+		$connection->dsn = $this->mongoConfig['dsn'] . '/' . $this->mongoConfig['defaultDatabaseName'];
+		$database = $connection->getDatabase();
+		$this->assertTrue($database instanceof Database, 'Unable to determine default database from dsn!');
+	}
+
+	/**
+	 * @depends testGetDefaultDatabase
+	 */
 	public function testGetCollection()
 	{
-		$connection = $this->getConnection(false);
+		$connection = $this->getConnection();
+
 		$collection = $connection->getCollection('customer');
-		$this->assertTrue($collection instanceof \MongoCollection);
+		$this->assertTrue($collection instanceof Collection);
+
+		$collection2 = $connection->getCollection('customer');
+		$this->assertTrue($collection === $collection2);
+
+		$collection2 = $connection->getCollection('customer', true);
+		$this->assertFalse($collection === $collection2);
 	}
 }
\ No newline at end of file
diff --git a/tests/unit/extensions/mongo/DatabaseTest.php b/tests/unit/extensions/mongo/DatabaseTest.php
new file mode 100644
index 0000000..ec0bf2d
--- /dev/null
+++ b/tests/unit/extensions/mongo/DatabaseTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace yiiunit\extensions\mongo;
+
+use yii\mongo\Collection;
+
+/**
+ * @group mongo
+ */
+class DatabaseTest extends MongoTestCase
+{
+	protected function tearDown()
+	{
+		$this->dropCollection('customer');
+		parent::tearDown();
+	}
+
+	// Tests :
+
+	public function testGetCollection()
+	{
+		$database = $connection = $this->getConnection()->getDatabase();
+
+		$collection = $database->getCollection('customer');
+		$this->assertTrue($collection instanceof Collection);
+		$this->assertTrue($collection->mongoCollection instanceof \MongoCollection);
+
+		$collection2 = $database->getCollection('customer');
+		$this->assertTrue($collection === $collection2);
+
+		$collectionRefreshed = $database->getCollection('customer', true);
+		$this->assertFalse($collection === $collectionRefreshed);
+	}
+}
\ No newline at end of file
diff --git a/tests/unit/extensions/mongo/MongoTestCase.php b/tests/unit/extensions/mongo/MongoTestCase.php
index a4f20ac..61f35c8 100644
--- a/tests/unit/extensions/mongo/MongoTestCase.php
+++ b/tests/unit/extensions/mongo/MongoTestCase.php
@@ -14,7 +14,7 @@ class MongoTestCase extends TestCase
 	 */
 	protected $mongoConfig = [
 		'dsn' => 'mongodb://localhost:27017',
-		'dbName' => 'yii2test',
+		'defaultDatabaseName' => 'yii2test',
 	];
 	/**
 	 * @var Connection Mongo connection instance.
@@ -76,8 +76,8 @@ class MongoTestCase extends TestCase
 		}
 		$db = new Connection;
 		$db->dsn = $this->mongoConfig['dsn'];
-		if (isset($this->mongoConfig['dbName'])) {
-			$db->dbName = $this->mongoConfig['dbName'];
+		if (isset($this->mongoConfig['defaultDatabaseName'])) {
+			$db->defaultDatabaseName = $this->mongoConfig['defaultDatabaseName'];
 		}
 		if (isset($this->mongoConfig['options'])) {
 			$db->options = $this->mongoConfig['options'];
--
libgit2 0.27.1