* @link http://netmonsters.ru * @package Majestic * @subpackage UnitTests * @since 2011-11-4 * * Unit tests for MySQLiStatement class */ require_once dirname(__FILE__) . '/../../Registry.php'; require_once dirname(__FILE__) . '/../../Config.php'; require_once dirname(__FILE__) . '/../../util/profiler/CommandProfiler.php'; require_once dirname(__FILE__) . '/../../util/profiler/Profiler.php'; require_once dirname(__FILE__) . '/../../model/Db.php'; require_once dirname(__FILE__) . '/../../model/DbDriver.php'; require_once dirname(__FILE__) . '/../../model/DbStatement.php'; require_once dirname(__FILE__) . '/../../model/MySQLiStatement.php'; require_once dirname(__FILE__) . '/../../exception/GeneralException.php'; class MySQLiStatementTest extends PHPUnit_Framework_TestCase { private $driver; private $stmt; private $sql; private $testData = array( array('one' => 11, 'two' => 12), array('one' => 21, 'two' => 22), array('one' => 31, 'two' => 32), ); public function run(PHPUnit_Framework_TestResult $result = NULL) { $this->setPreserveGlobalState(false); return parent::run($result); } public function setUp() { if (!isset($this->stmt)) { $this->driver = $this->getMockBuilder('DbDriverMock') ->disableOriginalConstructor() ->setMethods(array('quote', 'getConnection')) ->getMock(); $this->sql = 'SELECT * :place FROM :place AND :new'; $this->stmt = new MySQLiStatement($this->driver, $this->sql); } } public function testBindParam() { $val = $this->getMockBuilder('DbExpr') ->disableOriginalConstructor() ->getMock(); $this->assertFalse($this->stmt->bindParam('var', $val)); $this->assertTrue($this->stmt->bindParam('place', $val)); } public function testBindParamExceptionParam() { $val = 1; $this->setExpectedException('GeneralException', 'Placeholder must be an integer or string'); $this->stmt->bindParam(array(), $val); } public function testBindParamExceptionWrongObject() { $val = $this->getMock('NotDbExpr'); $this->setExpectedException('GeneralException', 'Objects excepts DbExpr not allowed.'); $this->stmt->bindParam('paa', $val); } /** * @runInSeparateProcess */ public function testExecute() { Config::set('PROFILER_DETAILS', false); $this->driver ->expects($this->any()) ->method('quote') ->with($this->anything()) ->will($this->returnCallback(array($this, 'driverQuote'))); $this->setDriverGetConnectionMethod(); $result = $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertTrue($result); } /** * @runInSeparateProcess */ public function testExecuteNoPlaceholders() { Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionMethod(); $this->sql = 'PLAIN SQL'; $result = $this->stmt->execute(array()); $this->assertTrue($result); } /** * @runInSeparateProcess * @group MySQL */ public function testFetchNoResult() { Config::set('PROFILER_DETAILS', false); $this->assertFalse($this->stmt->fetch()); } /** * @runInSeparateProcess * @group MySQL */ public function testDriverExecuteNoResult() { Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionWrongResultMethod(); $this->setExpectedException('GeneralException', 'ERROR'); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); } /** * @runInSeparateProcess * @group MySQL */ public function testFetch() { Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertSame('OBJECT', $this->stmt->fetch()); $this->assertSame('ARRAY', $this->stmt->fetch(Db::FETCH_NUM)); $this->assertSame('ASSOC', $this->stmt->fetch(Db::FETCH_ASSOC)); $this->assertSame('ARRAY', $this->stmt->fetch(Db::FETCH_BOTH)); } /** * @runInSeparateProcess * @group MySQL */ public function testFetchObject() { Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertSame('OBJECT', $this->stmt->fetchObject()); } /** * @runInSeparateProcess * @group MySQL */ public function testFetchPairs() { Config::set('PROFILER_DETAILS', false); $resultMock = $this->getMockBuilder('mysqli_result') ->disableOriginalConstructor() ->setMethods(array('fetch_array', 'close')) ->setMockClassName('Mysqli_Result_Mock') ->getMock(); $resultMock ->expects($this->at(0)) ->method('fetch_array') ->will($this->returnValue(array('pair', 'value'))); $resultMock ->expects($this->at(1)) ->method('fetch_array') ->will($this->returnValue(false)); $resultMock ->expects($this->any()) ->method('close') ->will($this->returnValue(TRUE)); $mysqliMock = $this->getMock('MysqliDrvr', array('query')); $mysqliMock ->expects($this->any()) ->method('query') ->with($this->anything()) ->will($this->returnValue($resultMock)); $this->driver ->expects($this->any()) ->method('getConnection') ->will($this->returnValue($mysqliMock)); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertSame(array('pair' => 'value'), $this->stmt->fetchPairs()); } /** * @runInSeparateProcess */ public function testFetchWithDebug() { Config::set('PROFILER', true); Config::set('PROFILER_DETAILS', true); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertSame('OBJECT', $this->stmt->fetch()); } /** * @runInSeparateProcess * @group MySQL */ public function testClose() { Config::set('PROFILER_DETAILS', false); $this->assertAttributeEquals(null, 'result', $this->stmt); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertAttributeNotEquals(null, 'result', $this->stmt); $this->stmt->close(); $this->assertAttributeEquals(null, 'result', $this->stmt); } /** * @group MySQL */ public function testAffectedRows() { $mysqliMock = $this->getMockBuilder('MysqliDrvr'); $mysqliMock->affected_rows = 'AFFECTED_ROWS'; $this->driver ->expects($this->any()) ->method('getConnection') ->will($this->returnValue($mysqliMock)); $this->assertSame('AFFECTED_ROWS', $this->stmt->affectedRows()); } /** * @group MySQL */ public function testNumRowsNoResult() { $this->assertFalse($this->stmt->numRows()); } /** * @runInSeparateProcess * @TODO: exception just for code coverage - could not mock mysqli properties * @group MySQL */ public function testNumRows() { $this->markTestSkipped('Unable to execute a method or access a property of an incomplete object.'); Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->assertNull($this->stmt->numRows()); } /** * @runInSeparateProcess * @group MySQL */ public function testFetchInvalidMode() { Config::set('PROFILER_DETAILS', false); $this->setDriverGetConnectionMethod(); $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val')); $this->setExpectedException('GeneralException'); $this->stmt->fetch(324); } private function setDriverGetConnectionMethod() { $resultMock = $this->getMockBuilder('mysqli_result') ->disableOriginalConstructor() ->setMethods(array('fetch_object', 'fetch_array', 'fetch_assoc', 'close')) ->setMockClassName('Mysqli_Result_Mock') ->getMock(); $resultMock ->expects($this->any()) ->method('fetch_object') ->will($this->returnValue('OBJECT')); $resultMock ->expects($this->any()) ->method('fetch_array') ->will($this->returnValue('ARRAY')); $resultMock ->expects($this->any()) ->method('fetch_assoc') ->will($this->returnValue('ASSOC')); $resultMock ->expects($this->any()) ->method('close') ->will($this->returnValue(TRUE)); $mysqliMock = $this->getMock('MysqliDrvr', array('query')); $mysqliMock ->expects($this->any()) ->method('query') ->with($this->anything()) ->will($this->returnValue($resultMock)); $this->driver ->expects($this->any()) ->method('getConnection') ->will($this->returnValue($mysqliMock)); return $this; } private function setDriverGetConnectionWrongResultMethod() { $mysqliMock = $this->getMock('MysqliDrvr', array('query')); $mysqliMock ->expects($this->any()) ->method('query') ->with($this->anything()) ->will($this->returnValue(false)); $mysqliMock->error = 'ERROR'; $mysqliMock->errno = 0; $this->driver ->expects($this->any()) ->method('getConnection') ->will($this->returnValue($mysqliMock)); return $this; } public function driverQuote($val) { return $val; } public function dbStatementAssemble($val) { return $val; } }