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.

377 lines
11 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. require_once dirname(__FILE__) . '/../../exception/GeneralException.php';
  18. class MySQLiStatementTest extends PHPUnit_Framework_TestCase
  19. {
  20. private $driver;
  21. private $stmt;
  22. private $sql;
  23. private $testData = array(
  24. array('one' => 11, 'two' => 12),
  25. array('one' => 21, 'two' => 22),
  26. array('one' => 31, 'two' => 32),
  27. );
  28. public function run(PHPUnit_Framework_TestResult $result = NULL)
  29. {
  30. $this->setPreserveGlobalState(false);
  31. return parent::run($result);
  32. }
  33. public function setUp()
  34. {
  35. if (!isset($this->stmt)) {
  36. $this->driver = $this->getMockBuilder('DbDriverMock')
  37. ->disableOriginalConstructor()
  38. ->setMethods(array('quote', 'getConnection'))
  39. ->getMock();
  40. $this->sql = 'SELECT * :place FROM :place AND :new';
  41. $this->stmt = new MySQLiStatement($this->driver, $this->sql);
  42. }
  43. }
  44. public function testBindParam()
  45. {
  46. $val = $this->getMockBuilder('DbExpr')
  47. ->disableOriginalConstructor()
  48. ->getMock();
  49. $this->assertFalse($this->stmt->bindParam('var', $val));
  50. $this->assertTrue($this->stmt->bindParam('place', $val));
  51. }
  52. /**
  53. * @expectedException Exception
  54. * @expectedExceptionMessage Placeholder must be an array or string
  55. * @TODO: change Exception Message 'Placeholder must be an array or string' - no arrays available
  56. */
  57. public function testBindParamExceptionParam()
  58. {
  59. $val = 1;
  60. $this->stmt->bindParam(array(), $val);
  61. }
  62. /**
  63. * @expectedException Exception
  64. * @expectedExceptionMessage Objects excepts DbExpr not allowed.
  65. */
  66. public function testBindParamExceptionWrongObject()
  67. {
  68. $val = $this->getMock('NotDbExpr');
  69. $this->stmt->bindParam('paa', $val);
  70. }
  71. /**
  72. * @runInSeparateProcess
  73. */
  74. public function testExecute()
  75. {
  76. if (!defined('DEBUG')) {
  77. define('DEBUG', false);
  78. }
  79. $this->driver
  80. ->expects($this->any())
  81. ->method('quote')
  82. ->with($this->anything())
  83. ->will($this->returnCallback(array($this, 'driverQuote')));
  84. $this->setDriverGetConnectionMethod();
  85. $result = $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  86. $this->assertEquals('SELECT * place_val FROM place_val AND new_val', $result);
  87. }
  88. /**
  89. * @runInSeparateProcess
  90. */
  91. public function testExecuteNoPlaceholders()
  92. {
  93. if (!defined('DEBUG')) {
  94. define('DEBUG', false);
  95. }
  96. $this->setDriverGetConnectionMethod();
  97. $this->sql = 'PLAIN SQL';
  98. $result = $this->stmt->execute(array());
  99. $this->assertEquals('PLAIN SQL', $result);
  100. }
  101. /**
  102. * @runInSeparateProcess
  103. * @group MySQL
  104. */
  105. public function testFetchNoResult()
  106. {
  107. if (!defined('DEBUG')) {
  108. define('DEBUG', false);
  109. }
  110. $this->assertFalse($this->stmt->fetch());
  111. }
  112. /**
  113. * @runInSeparateProcess
  114. * @group MySQL
  115. */
  116. public function testDriverExecuteNoResult()
  117. {
  118. if (!defined('DEBUG')) {
  119. define('DEBUG', false);
  120. }
  121. $this->setDriverGetConnectionWrongResultMethod();
  122. $this->setExpectedException('GeneralException', 'ERROR');
  123. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  124. }
  125. /**
  126. * @runInSeparateProcess
  127. * @group MySQL
  128. */
  129. public function testFetch()
  130. {
  131. if (!defined('DEBUG')) {
  132. define('DEBUG', false);
  133. }
  134. $this->setDriverGetConnectionMethod();
  135. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  136. $this->assertSame('OBJECT', $this->stmt->fetch());
  137. $this->assertSame('ARRAY', $this->stmt->fetch(Db::FETCH_NUM));
  138. $this->assertSame('ASSOC', $this->stmt->fetch(Db::FETCH_ASSOC));
  139. $this->assertSame('ARRAY', $this->stmt->fetch(Db::FETCH_BOTH));
  140. }
  141. /**
  142. * @runInSeparateProcess
  143. * @group MySQL
  144. */
  145. public function testFetchObject()
  146. {
  147. if (!defined('DEBUG')) {
  148. define('DEBUG', false);
  149. }
  150. $this->setDriverGetConnectionMethod();
  151. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  152. $this->assertSame('OBJECT', $this->stmt->fetchObject());
  153. }
  154. /**
  155. * @runInSeparateProcess
  156. * @group MySQL
  157. */
  158. public function testFetchPairs()
  159. {
  160. if (!defined('DEBUG')) {
  161. define('DEBUG', false);
  162. }
  163. $resultMock = $this->getMockBuilder('mysqli_result')
  164. ->disableOriginalConstructor()
  165. ->setMethods(array('fetch_array', 'close'))
  166. ->setMockClassName('Mysqli_Result_Mock')
  167. ->getMock();
  168. $resultMock
  169. ->expects($this->at(0))
  170. ->method('fetch_array')
  171. ->will($this->returnValue(array('pair', 'value')));
  172. $resultMock
  173. ->expects($this->at(1))
  174. ->method('fetch_array')
  175. ->will($this->returnValue(false));
  176. $resultMock
  177. ->expects($this->any())
  178. ->method('close')
  179. ->will($this->returnValue(TRUE));
  180. $mysqliMock = $this->getMock('MysqliDrvr', array('query'));
  181. $mysqliMock
  182. ->expects($this->any())
  183. ->method('query')
  184. ->with($this->anything())
  185. ->will($this->returnValue($resultMock));
  186. $this->driver
  187. ->expects($this->any())
  188. ->method('getConnection')
  189. ->will($this->returnValue($mysqliMock));
  190. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  191. $this->assertEquals(array('pair' => 'value'), $this->stmt->fetchPairs());
  192. }
  193. /**
  194. * @runInSeparateProcess
  195. */
  196. public function testFetchWithDebug()
  197. {
  198. if (!defined('DEBUG')) {
  199. define('DEBUG', true);
  200. }
  201. $this->setDriverGetConnectionMethod();
  202. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  203. $this->assertSame('OBJECT', $this->stmt->fetch());
  204. }
  205. /**
  206. * @runInSeparateProcess
  207. * @group MySQL
  208. */
  209. public function testClose()
  210. {
  211. if (!defined('DEBUG')) {
  212. define('DEBUG', false);
  213. }
  214. $this->assertAttributeEquals(null, 'result', $this->stmt);
  215. $this->setDriverGetConnectionMethod();
  216. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  217. $this->assertAttributeNotEquals(null, 'result', $this->stmt);
  218. $this->stmt->close();
  219. $this->assertAttributeEquals(null, 'result', $this->stmt);
  220. }
  221. /**
  222. * @group MySQL
  223. */
  224. public function testAffectedRows()
  225. {
  226. $mysqliMock = $this->getMockBuilder('MysqliDrvr');
  227. $mysqliMock->affected_rows = 'AFFECTED_ROWS';
  228. $this->driver
  229. ->expects($this->any())
  230. ->method('getConnection')
  231. ->will($this->returnValue($mysqliMock));
  232. $this->assertSame('AFFECTED_ROWS', $this->stmt->affectedRows());
  233. }
  234. /**
  235. * @group MySQL
  236. */
  237. public function testNumRowsNoResult()
  238. {
  239. $this->assertFalse($this->stmt->numRows());
  240. }
  241. /**
  242. * @runInSeparateProcess
  243. * @TODO: exception just for code coverage - could not mock mysqli properties
  244. * @group MySQL
  245. */
  246. public function testNumRows()
  247. {
  248. $this->markTestSkipped('Unable to execute a method or access a property of an incomplete object.');
  249. if (!defined('DEBUG')) {
  250. define('DEBUG', false);
  251. }
  252. $this->setDriverGetConnectionMethod();
  253. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  254. $this->assertNull($this->stmt->numRows());
  255. }
  256. /**
  257. * @runInSeparateProcess
  258. * @group MySQL
  259. */
  260. public function testFetchInvalidMode()
  261. {
  262. if (!defined('DEBUG')) {
  263. define('DEBUG', false);
  264. }
  265. $this->setDriverGetConnectionMethod();
  266. $this->stmt->execute(array('place' => 'place_val', 'new' => 'new_val'));
  267. $this->setExpectedException('GeneralException');
  268. $this->stmt->fetch(324);
  269. }
  270. private function setDriverGetConnectionMethod()
  271. {
  272. $resultMock = $this->getMockBuilder('mysqli_result')
  273. ->disableOriginalConstructor()
  274. ->setMethods(array('fetch_object', 'fetch_array', 'fetch_assoc', 'close'))
  275. ->setMockClassName('Mysqli_Result_Mock')
  276. ->getMock();
  277. $resultMock
  278. ->expects($this->any())
  279. ->method('fetch_object')
  280. ->will($this->returnValue('OBJECT'));
  281. $resultMock
  282. ->expects($this->any())
  283. ->method('fetch_array')
  284. ->will($this->returnValue('ARRAY'));
  285. $resultMock
  286. ->expects($this->any())
  287. ->method('fetch_assoc')
  288. ->will($this->returnValue('ASSOC'));
  289. $resultMock
  290. ->expects($this->any())
  291. ->method('close')
  292. ->will($this->returnValue(TRUE));
  293. $mysqliMock = $this->getMock('MysqliDrvr', array('query'));
  294. $mysqliMock
  295. ->expects($this->any())
  296. ->method('query')
  297. ->with($this->anything())
  298. ->will($this->returnValue($resultMock));
  299. $this->driver
  300. ->expects($this->any())
  301. ->method('getConnection')
  302. ->will($this->returnValue($mysqliMock));
  303. return $this;
  304. }
  305. private function setDriverGetConnectionWrongResultMethod()
  306. {
  307. $mysqliMock = $this->getMock('MysqliDrvr', array('query'));
  308. $mysqliMock
  309. ->expects($this->any())
  310. ->method('query')
  311. ->with($this->anything())
  312. ->will($this->returnValue(false));
  313. $mysqliMock->error = 'ERROR';
  314. $mysqliMock->errno = 0;
  315. $this->driver
  316. ->expects($this->any())
  317. ->method('getConnection')
  318. ->will($this->returnValue($mysqliMock));
  319. return $this;
  320. }
  321. public function driverQuote($val)
  322. {
  323. return $val;
  324. }
  325. public function dbStatementAssemble($val)
  326. {
  327. return $val;
  328. }
  329. }