You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
9.2 KiB

  1. <?php
  2. /*
  3. * @copyright NetMonsters <team@netmonsters.ru>
  4. * @link http://netmonsters.ru
  5. * @package Majestic
  6. * @subpackage UnitTests
  7. * @since 2011-11-4
  8. *
  9. * Unit tests for MySQLiStatement class
  10. */
  11. require_once dirname(__FILE__) . '/../../util/profiler/CommandProfiler.php';
  12. require_once dirname(__FILE__) . '/../../util/profiler/Profiler.php';
  13. require_once dirname(__FILE__) . '/../../model/Db.php';
  14. require_once dirname(__FILE__) . '/../../model/DbDriver.php';
  15. require_once dirname(__FILE__) . '/../../model/DbStatement.php';
  16. require_once dirname(__FILE__) . '/../../model/MySQLiStatement.php';
  17. class MySQLiStatementTest extends PHPUnit_Framework_TestCase
  18. {
  19. private $driver;
  20. private $stmt;
  21. private $sql;
  22. private $testData = array(
  23. array('one' => 11, 'two' => 12),
  24. array('one' => 21, 'two' => 22),
  25. array('one' => 31, 'two' => 32),
  26. );
  27. public function run(PHPUnit_Framework_TestResult $result = NULL)
  28. {
  29. $this->setPreserveGlobalState(false);
  30. return parent::run($result);
  31. }
  32. public function setUp()
  33. {
  34. if (!isset($this->stmt)) {
  35. $this->driver = $this->getMockBuilder('DbDriverMock')
  36. ->disableOriginalConstructor()
  37. ->setMethods(array('quote', 'getConnection'))
  38. ->getMock();
  39. $this->sql = 'SELECT * :place FROM :place AND :new';
  40. $this->stmt = new MySQLiStatement($this->driver, $this->sql);
  41. }
  42. }
  43. public function testBindParam()
  44. {
  45. $val = $this->getMockBuilder('DbExpr')
  46. ->disableOriginalConstructor()
  47. ->getMock();
  48. $this->assertFalse($this->stmt->bindParam('var', $val));
  49. $this->assertTrue($this->stmt->bindParam('place', $val));
  50. }
  51. /**
  52. * @expectedException Exception
  53. * @expectedExceptionMessage Placeholder must be an array or string
  54. * @TODO: change Exception Message 'Placeholder must be an array or string' - no arrays available
  55. */
  56. public function testBindParamExceptionParam()
  57. {
  58. $val = 1;
  59. $this->stmt->bindParam(array(), $val);
  60. }
  61. /**
  62. * @expectedException Exception
  63. * @expectedExceptionMessage Objects excepts DbExpr not allowed.
  64. */
  65. public function testBindParamExceptionWrongObject()
  66. {
  67. $val = $this->getMock('NotDbExpr');
  68. $this->stmt->bindParam('paa', $val);
  69. }
  70. /**
  71. * @runInSeparateProcess
  72. */
  73. public function testExecute()
  74. {
  75. if (!defined('DEBUG')) {
  76. define('DEBUG', false);
  77. }
  78. $this->driver
  79. ->expects($this->any())
  80. ->method('quote')
  81. ->with($this->anything())
  82. ->will($this->returnCallback(array($this, 'driverQuote')));
  83. $this->setDriverGetConnectionMethod();
  84. $result = $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  85. $this->assertEquals('SELECT * place_val FROM place_val AND new_val', $result);
  86. }
  87. /**
  88. * @runInSeparateProcess
  89. */
  90. public function testExecuteNoPlaceholders()
  91. {
  92. if (!defined('DEBUG')) {
  93. define('DEBUG', false);
  94. }
  95. $this->setDriverGetConnectionMethod();
  96. $this->sql = 'PLAIN SQL';
  97. $result = $this->stmt->execute(array());
  98. $this->assertEquals('PLAIN SQL', $result);
  99. }
  100. /**
  101. * @runInSeparateProcess
  102. */
  103. public function testFetchNoResult()
  104. {
  105. if (!defined('DEBUG')) {
  106. define('DEBUG', false);
  107. }
  108. $this->assertFalse($this->stmt->fetch());
  109. }
  110. /**
  111. * @runInSeparateProcess
  112. * @expectedException Exception
  113. * @expectedExceptionMessage ERROR
  114. */
  115. public function testDriverExecuteNoResult()
  116. {
  117. if (!defined('DEBUG')) {
  118. define('DEBUG', false);
  119. }
  120. $this->setDriverGetConnectionWrongResultMethod();
  121. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  122. }
  123. /**
  124. * @runInSeparateProcess
  125. */
  126. public function testFetch()
  127. {
  128. if (!defined('DEBUG')) {
  129. define('DEBUG', false);
  130. }
  131. $this->setDriverGetConnectionMethod();
  132. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  133. $this->assertEquals('OBJECT', $this->stmt->fetch());
  134. $this->assertEquals('ARRAY', $this->stmt->fetch(Db::FETCH_NUM));
  135. $this->assertEquals('ASSOC', $this->stmt->fetch(Db::FETCH_ASSOC));
  136. $this->assertEquals('ARRAY', $this->stmt->fetch(Db::FETCH_BOTH));
  137. }
  138. /**
  139. * @runInSeparateProcess
  140. */
  141. public function testFetchObject()
  142. {
  143. if (!defined('DEBUG')) {
  144. define('DEBUG', false);
  145. }
  146. $this->setDriverGetConnectionMethod();
  147. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  148. $this->assertEquals('OBJECT', $this->stmt->fetchObject());
  149. }
  150. /**
  151. * @runInSeparateProcess
  152. */
  153. public function testFetchWithDebug()
  154. {
  155. if (!defined('DEBUG')) {
  156. define('DEBUG', true);
  157. }
  158. $this->setDriverGetConnectionMethod();
  159. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  160. $this->assertEquals('OBJECT', $this->stmt->fetch());
  161. }
  162. /**
  163. * @runInSeparateProcess
  164. */
  165. public function testClose()
  166. {
  167. if (!defined('DEBUG')) {
  168. define('DEBUG', false);
  169. }
  170. $this->assertAttributeEquals(null, 'result', $this->stmt);
  171. $this->setDriverGetConnectionMethod();
  172. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  173. $this->assertAttributeNotEquals(null, 'result', $this->stmt);
  174. $this->stmt->close();
  175. $this->assertAttributeEquals(null, 'result', $this->stmt);
  176. }
  177. public function testAffectedRows()
  178. {
  179. $mysqliMock = $this->getMockBuilder('MysqliDrvr');
  180. $mysqliMock->affected_rows = 'AFFECTED_ROWS';
  181. $this->driver
  182. ->expects($this->any())
  183. ->method('getConnection')
  184. ->will($this->returnValue($mysqliMock));
  185. $this->assertEquals('AFFECTED_ROWS', $this->stmt->affectedRows());
  186. }
  187. public function testNumRowsNoResult()
  188. {
  189. $this->assertFalse($this->stmt->numRows());
  190. }
  191. /**
  192. * @runInSeparateProcess
  193. * @expectedException Exception
  194. * @TODO: exception just for code coverage - could not mock mysqli properties
  195. */
  196. public function testNumRows()
  197. {
  198. if (!defined('DEBUG')) {
  199. define('DEBUG', false);
  200. }
  201. $this->setDriverGetConnectionMethod();
  202. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  203. $this->assertNull($this->stmt->numRows());
  204. }
  205. /**
  206. * @expectedException Exception
  207. * @expectedExceptionMessage Invalid fetch mode
  208. * @runInSeparateProcess
  209. */
  210. public function testFetchInvalidMode()
  211. {
  212. if (!defined('DEBUG')) {
  213. define('DEBUG', false);
  214. }
  215. $this->setDriverGetConnectionMethod();
  216. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  217. $this->stmt->fetch(324);
  218. }
  219. private function setDriverGetConnectionMethod()
  220. {
  221. $resultMock = $this->getMockBuilder('mysqli_result')
  222. ->disableOriginalConstructor()
  223. ->setMethods(array('fetch_object', 'fetch_array', 'fetch_assoc', 'close'))
  224. ->setMockClassName('Mysqli_Result_Mock')
  225. ->getMock();
  226. $resultMock
  227. ->expects($this->any())
  228. ->method('fetch_object')
  229. ->will($this->returnValue('OBJECT'));
  230. $resultMock
  231. ->expects($this->any())
  232. ->method('fetch_array')
  233. ->will($this->returnValue('ARRAY'));
  234. $resultMock
  235. ->expects($this->any())
  236. ->method('fetch_assoc')
  237. ->will($this->returnValue('ASSOC'));
  238. $resultMock
  239. ->expects($this->any())
  240. ->method('close')
  241. ->will($this->returnValue(TRUE));
  242. $mysqliMock = $this->getMock('MysqliDrvr', array('query'));
  243. $mysqliMock
  244. ->expects($this->any())
  245. ->method('query')
  246. ->with($this->anything())
  247. ->will($this->returnValue($resultMock));
  248. $this->driver
  249. ->expects($this->any())
  250. ->method('getConnection')
  251. ->will($this->returnValue($mysqliMock));
  252. return $this;
  253. }
  254. private function setDriverGetConnectionWrongResultMethod()
  255. {
  256. $mysqliMock = $this->getMock('MysqliDrvr', array('query'));
  257. $mysqliMock
  258. ->expects($this->any())
  259. ->method('query')
  260. ->with($this->anything())
  261. ->will($this->returnValue(false));
  262. $mysqliMock->error = 'ERROR';
  263. $mysqliMock->errno = 0;
  264. $this->driver
  265. ->expects($this->any())
  266. ->method('getConnection')
  267. ->will($this->returnValue($mysqliMock));
  268. return $this;
  269. }
  270. public function driverQuote($val)
  271. {
  272. return $val;
  273. }
  274. public function dbStatementAssemble($val)
  275. {
  276. return $val;
  277. }
  278. }