* @link http://netmonsters.ru * @package Majestic * @subpackage UnitTests * @since 2011-11-7 * * Unit tests for MongoModel class */ require_once dirname(__FILE__) . '/../../Registry.php'; require_once dirname(__FILE__) . '/../../Config.php'; require_once dirname(__FILE__) . '/../../cache/Cacher.php'; require_once dirname(__FILE__) . '/../../exception/GeneralException.php'; require_once dirname(__FILE__) . '/../../model/DbExpr.php'; require_once dirname(__FILE__) . '/../../model/Db.php'; require_once dirname(__FILE__) . '/../../model/MongoDbCommand.php'; require_once dirname(__FILE__) . '/../../model/DbStatement.php'; require_once dirname(__FILE__) . '/../../model/MongoStatement.php'; require_once dirname(__FILE__) . '/../../model/DbDriver.php'; require_once dirname(__FILE__) . '/../../model/NoSqlDbDriver.php'; require_once dirname(__FILE__) . '/../../model/MongoDriver.php'; require_once dirname(__FILE__) . '/../../model/Model.php'; require_once dirname(__FILE__) . '/../../model/MongoModel.php'; class MongoModelTest extends PHPUnit_Framework_TestCase { /** * @var MongoModel */ private $model; /** * @var ReflectionMethod */ private $method_count; /** * @var ReflectionMethod */ private $method_fetch; public function run(PHPUnit_Framework_TestResult $result = NULL) { $this->setPreserveGlobalState(false); return parent::run($result); } public function setUp() { $conf = array('default' => array('driver' => 'MongoDriver', 'hostname' => 'localhost', 'database' => 'test', 'username' => 'test', 'password' => '1234', 'port' => 27017)); $this->dbSetUp($conf); Config::set('Db', $conf); if (!class_exists('MockModel')) { $this->model = $this->getMockForAbstractClass('MongoModel', array(), 'MongoMockModel'); } else { $this->model = new MongoMockModel(); } $model = new ReflectionClass('MongoModel'); $this->method_count = $model->getMethod('count'); $this->method_count->setAccessible(true); $this->method_fetch = $model->getMethod('fetch'); $this->method_fetch->setAccessible(true); set_new_overload(array($this, 'newCallback')); } /** * @group Mongo */ public function testModel() { $this->assertInstanceOf('MongoMockModel', $this->model); } /** * @runInSeparateProcess * @group Mongo */ public function testFetch() { Config::set('DEBUG', false); $mock = $this->getMock('CacheKey', array('set', 'get')); $mock->expects($this->once()) ->method('set') ->will($this->returnValue(true)); $mock->expects($this->once()) ->method('get') ->will($this->returnValue(false)); $result = $this->method_fetch->invoke($this->model, array(), array('order' => array('name' => -1), 'limit' => 2), $mock); $this->assertInstanceOf('ArrayObject', $result); $this->assertEquals('milk', $result->name); $result = $this->method_fetch->invoke($this->model, array(), array('fields' => array('name'))); $this->assertSame('bread', $result->name); $result = $this->method_fetch->invoke($this->model, array()); $this->setExpectedException('PHPUnit_Framework_Error'); $this->assertNull($result->pounds); } /** * @runInSeparateProcess * @group Mongo */ public function testFetchField() { Config::set('DEBUG', false); $mock = $this->getMock('CacheKey', array('set', 'get')); $mock->expects($this->exactly(2)) ->method('set') ->will($this->returnValue(true)); $mock->expects($this->exactly(2)) ->method('get') ->will($this->returnValue(false)); $model = new ReflectionClass('MongoModel'); $method = $model->getMethod('fetchField'); $method->setAccessible(true); $result = $method->invoke($this->model, array('name' => 'milk'), array(), 'quantity', $mock); $this->assertEquals(1, $result); $result = $method->invoke($this->model, array(), array('skip' => 2), 'quantity', $mock); $this->assertEquals($result, $this->method_fetch->invoke($this->model, array(), array('skip' => 2))->quantity); } /** * @runInSeparateProcess * @group Mongo */ public function testFetchAll() { Config::set('DEBUG', false); $mock = $this->getMock('CacheKey', array('set', 'get')); $mock->expects($this->once()) ->method('set') ->will($this->returnValue(true)); $mock->expects($this->once()) ->method('get') ->will($this->returnValue(false)); $model = new ReflectionClass('MongoModel'); $method = $model->getMethod('fetchAll'); $method->setAccessible(true); $result = $method->invoke($this->model, array('name' => 'eggs'), array(), $mock); $this->assertEquals(2, count($result)); $result = $method->invoke($this->model, array(), array('skip' => 2)); $this->assertEquals(3, count($result)); $this->assertEquals('fish', $result[0]->name); $this->assertEquals('milk', $result[1]->name); $this->assertEquals('eggs', $result[2]->name); } /** * @runInSeparateProcess * @group Mongo */ public function testFetchOrderParam() { Config::set('DEBUG', false); $result = $this->method_fetch->invoke($this->model, array(), array('order' => 'name')); $this->assertSame('bread', $result->name); $result = $this->method_fetch->invoke($this->model, array(), array('order' => array('name' => 1, 'quantity' => -1), 'skip' => 1)); $this->assertSame(2.1, $result->price); $this->setExpectedException('GeneralException', 'Wrong order parameter given to query.'); $this->method_fetch->invoke($this->model, array(), array('order' => 1)); } /** * @runInSeparateProcess * @group Mongo */ public function testFetchSkipLimitParam() { Config::set('DEBUG', false); $result = $this->method_fetch->invoke($this->model, array(), array('order' => 'name')); $this->assertSame('bread', $result->name); $result = $this->method_fetch->invoke($this->model, array(), array('order' => array('name' => 1, 'quantity' => -1), 'skip' => 1, 'limit' => 1)); $this->assertSame(2.1, $result->price); $model = new ReflectionClass('MongoModel'); $method = $model->getMethod('fetchAll'); $method->setAccessible(true); $this->assertCount(3, $method->invoke($this->model, array(), array('limit' => 3))); $this->assertCount(2, $method->invoke($this->model, array(), array('skip' => 3))); $this->assertCount(5, $method->invoke($this->model, array(), array())); } /** * @runInSeparateProcess * @group Mongo */ public function testFetchFieldsParam() { Config::set('DEBUG', false); $result = $this->method_fetch->invoke($this->model, array(), array('fields' => 'name')); $this->assertTrue(!isset($result->quantity)); $result = $this->method_fetch->invoke($this->model, array(), array('fields' => array('name', 'price'))); $this->assertTrue(!isset($result->quantity)); $result = $this->method_fetch->invoke($this->model, array(), array('fields' => array('name' => 1, 'price' => 1))); $this->assertTrue(!isset($result->quantity)); $this->setExpectedException('GeneralException', 'Wrong fields parameter given to query.'); $this->method_fetch->invoke($this->model, array(), array('fields' => 1)); } /** * @runInSeparateProcess * @group Mongo */ public function testGet() { Config::set('DEBUG', false); $result = $this->method_fetch->invoke($this->model, array(), array('order' => array('name' => 1))); $this->assertEquals('bread', $result->name); $id = $result->_id; $this->assertEquals(10, $this->model->get($id)->quantity); } /** * @runInSeparateProcess * @group Mongo */ public function testDelete() { Config::set('DEBUG', false); $result = $this->method_fetch->invoke($this->model, array(), array('order' => array('name' => 1))); $id = $result->_id; $this->assertEquals(1, $this->model->delete($id)); $this->assertFalse($this->method_fetch->invoke($this->model, array('name' => 'bread'))); } /** * @runInSeparateProcess * @group Mongo */ public function testUpdate() { Config::set('DEBUG', false); $this->model->insert(array('name' => 'testbread', 'price' => 3.2, 'quantity' => 10)); $result = $this->method_fetch->invoke($this->model, array('name' => 'testbread')); $this->assertEquals(10, $result->quantity); $this->model->update(array('$set' => array('quantity' => 3)), $result->_id); $this->assertEquals(3, $this->model->get($result->_id)->quantity); $this->model->update(array('$set' => array('quantity' => 13)), (string)$result->_id); $this->assertEquals(13, $this->model->get($result->_id)->quantity); } /** * @runInSeparateProcess * @group Mongo */ public function testBatchInsert() { Config::set('DEBUG', false); $data = array( array('name' => 'first object'), array('name' => 'second object'), array('name' => 'equal object'), array('name' => 'equal object') ); $this->model->batchInsert($data); $this->assertEquals(1, $this->method_count->invoke($this->model, array('name' => 'first object'))); $this->assertEquals(2, $this->method_count->invoke($this->model, array('name' => 'equal object'))); } /** * @runInSeparateProcess * @group Mongo */ public function testCount() { Config::set('DEBUG', false); $this->assertEquals(5, $this->method_count->invoke($this->model)); $this->assertEquals(2, $this->method_count->invoke($this->model, array('name' => 'eggs'))); } /** * @runInSeparateProcess * @group Mongo */ public function testUseMongoId() { Config::set('DEBUG', false); $this->assertAttributeEquals(true, 'useMongoId', $this->model); } /** * @runInSeparateProcess * @group Mongo */ public function testId() { Config::set('DEBUG', false); $class = new ReflectionClass('MongoModel'); $prop = $class->getProperty('useMongoId'); $prop->setAccessible(true); $this->model->insert(array('_id' => 1, 'name' => 'testbread', 'price' => 3.2, 'quantity' => 10)); $this->model->insert(array('_id' => 2, 'name' => 'testbread', 'price' => 12, 'quantity' => 2)); $this->assertSame(2, $this->method_count->invoke($this->model, array('name' => 'testbread'))); $prop->setValue($this->model, false); $this->model->delete(1); $this->assertSame(1, $this->method_count->invoke($this->model, array('name' => 'testbread'))); } /** * @runInSeparateProcess * @group Mongo */ public function testIdToMongoId() { Config::set('DEBUG', false); $this->model->insert(array('name' => 'testbread', 'price' => 3.2, 'quantity' => 10)); $this->model->insert(array('name' => 'testbread', 'price' => 12, 'quantity' => 2)); $this->assertSame(2, $this->method_count->invoke($this->model, array('name' => 'testbread'))); $id = $this->method_fetch->invoke($this->model, array('name' => 'testbread'))->_id->__toString(); $this->assertInternalType('string', $id); $item = $this->model->get($id); $this->assertSame('testbread', $item->name); $this->model->delete($id); $this->assertSame(1, $this->method_count->invoke($this->model, array('name' => 'testbread'))); } public function tearDown() { $conf = array('driver' => 'MongoDriver', 'hostname' => 'localhost', 'database' => 'test', 'username' => 'test', 'password' => '1234', 'port' => 27017); $connection = new Mongo('mongodb://' . $conf['hostname'] . ':' . $conf['port']); $db = $connection->selectDB($conf['database']); $db->authenticate($conf['username'], $conf['password']); $collection = 'mongomock'; $db->selectCollection($collection)->remove(array()); } protected function newCallback($className) { switch ($className) { case 'CacheKey': return 'MockCacheKey'; default: return $className; } } public function dbSetUp($conf) { $data = array( array( 'name' => 'bread', 'price' => 3.2, 'quantity' => 10 ), array( 'name' => 'eggs', 'price' => 2.1, 'quantity' => 20 ), array( 'name' => 'fish', 'price' => 13.2, 'quantity' => 2 ), array( 'name' => 'milk', 'price' => 3.8, 'quantity' => 1 ), array( 'name' => 'eggs', 'price' => 2.3, 'quantity' => 5 ) ); $connection = new Mongo('mongodb://' . $conf['default']['hostname'] . ':' . $conf['default']['port']); $db = $connection->selectDB($conf['default']['database']); $db->authenticate($conf['default']['username'], $conf['default']['password']); $collection = 'mongomock'; $db->dropCollection($collection); $collection = $db->selectCollection($collection); foreach ($data as $document) { $collection->insert($document); } } }