TestFixtureTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\TestSuite;
  16. use Cake\Database\Schema\Table;
  17. use Cake\Datasource\ConnectionManager;
  18. use Cake\Log\Log;
  19. use Cake\TestSuite\Fixture\TestFixture;
  20. use Cake\TestSuite\TestCase;
  21. use Exception;
  22. /**
  23. * ArticlesFixture class
  24. */
  25. class ArticlesFixture extends TestFixture
  26. {
  27. /**
  28. * Table property
  29. *
  30. * @var string
  31. */
  32. public $table = 'articles';
  33. /**
  34. * Fields array
  35. *
  36. * @var array
  37. */
  38. public $fields = [
  39. 'id' => ['type' => 'integer'],
  40. 'name' => ['type' => 'string', 'length' => '255'],
  41. 'created' => ['type' => 'datetime'],
  42. '_constraints' => [
  43. 'primary' => ['type' => 'primary', 'columns' => ['id']]
  44. ]
  45. ];
  46. /**
  47. * Records property
  48. *
  49. * @var array
  50. */
  51. public $records = [
  52. ['name' => 'Gandalf', 'created' => '2009-04-28 19:20:00'],
  53. ['name' => 'Captain Picard', 'created' => '2009-04-28 19:20:00'],
  54. ['name' => 'Chewbacca', 'created' => '2009-04-28 19:20:00']
  55. ];
  56. }
  57. /**
  58. * StringsTestsFixture class
  59. */
  60. class StringsTestsFixture extends TestFixture
  61. {
  62. /**
  63. * Table property
  64. *
  65. * @var string
  66. */
  67. public $table = 'strings';
  68. /**
  69. * Fields array
  70. *
  71. * @var array
  72. */
  73. public $fields = [
  74. 'id' => ['type' => 'integer'],
  75. 'name' => ['type' => 'string', 'length' => '255'],
  76. 'email' => ['type' => 'string', 'length' => '255'],
  77. 'age' => ['type' => 'integer', 'default' => 10]
  78. ];
  79. /**
  80. * Records property
  81. *
  82. * @var array
  83. */
  84. public $records = [
  85. ['name' => 'Mark Doe', 'email' => 'mark.doe@email.com'],
  86. ['name' => 'John Doe', 'email' => 'john.doe@email.com', 'age' => 20],
  87. ['email' => 'jane.doe@email.com', 'name' => 'Jane Doe', 'age' => 30]
  88. ];
  89. }
  90. /**
  91. * ImportsFixture class
  92. */
  93. class ImportsFixture extends TestFixture
  94. {
  95. /**
  96. * Import property
  97. *
  98. * @var mixed
  99. */
  100. public $import = ['table' => 'posts', 'connection' => 'test'];
  101. /**
  102. * Records property
  103. *
  104. * @var array
  105. */
  106. public $records = [
  107. ['title' => 'Hello!', 'body' => 'Hello world!']
  108. ];
  109. }
  110. /**
  111. * This class allows testing the fixture data insertion when the properties
  112. * $fields and $import are not set
  113. */
  114. class LettersFixture extends TestFixture
  115. {
  116. /**
  117. * records property
  118. *
  119. * @var array
  120. */
  121. public $records = [
  122. ['letter' => 'a'],
  123. ['letter' => 'b'],
  124. ['letter' => 'c']
  125. ];
  126. }
  127. /**
  128. * Test case for TestFixture
  129. */
  130. class TestFixtureTest extends TestCase
  131. {
  132. /**
  133. * Fixtures for this test.
  134. *
  135. * @var array
  136. */
  137. public $fixtures = ['core.posts'];
  138. /**
  139. * Set up
  140. *
  141. * @return void
  142. */
  143. public function setUp()
  144. {
  145. parent::setUp();
  146. Log::reset();
  147. }
  148. /**
  149. * Tear down
  150. *
  151. * @return void
  152. */
  153. public function tearDown()
  154. {
  155. parent::tearDown();
  156. Log::reset();
  157. }
  158. /**
  159. * test initializing a static fixture
  160. *
  161. * @return void
  162. */
  163. public function testInitStaticFixture()
  164. {
  165. $Fixture = new ArticlesFixture();
  166. $this->assertEquals('articles', $Fixture->table);
  167. $Fixture = new ArticlesFixture();
  168. $Fixture->table = null;
  169. $Fixture->init();
  170. $this->assertEquals('articles', $Fixture->table);
  171. $schema = $Fixture->schema();
  172. $this->assertInstanceOf('Cake\Database\Schema\Table', $schema);
  173. $fields = $Fixture->fields;
  174. unset($fields['_constraints'], $fields['_indexes']);
  175. $this->assertEquals(
  176. array_keys($fields),
  177. $schema->columns(),
  178. 'Fields do not match'
  179. );
  180. $this->assertEquals(array_keys($Fixture->fields['_constraints']), $schema->constraints());
  181. $this->assertEmpty($schema->indexes());
  182. }
  183. /**
  184. * test import fixture initialization
  185. *
  186. * @return void
  187. */
  188. public function testInitImport()
  189. {
  190. $fixture = new ImportsFixture();
  191. $fixture->fields = $fixture->records = null;
  192. $fixture->import = [
  193. 'table' => 'posts',
  194. 'connection' => 'test',
  195. ];
  196. $fixture->init();
  197. $expected = [
  198. 'id',
  199. 'author_id',
  200. 'title',
  201. 'body',
  202. 'published',
  203. ];
  204. $this->assertEquals($expected, $fixture->schema()->columns());
  205. }
  206. /**
  207. * test import fixture initialization
  208. *
  209. * @return void
  210. */
  211. public function testInitImportModel()
  212. {
  213. $fixture = new ImportsFixture();
  214. $fixture->fields = $fixture->records = null;
  215. $fixture->import = [
  216. 'model' => 'Posts',
  217. 'connection' => 'test',
  218. ];
  219. $fixture->init();
  220. $expected = [
  221. 'id',
  222. 'author_id',
  223. 'title',
  224. 'body',
  225. 'published',
  226. ];
  227. $this->assertEquals($expected, $fixture->schema()->columns());
  228. }
  229. /**
  230. * test schema reflection without $import or $fields and without the table existing
  231. * it will throw an exception
  232. *
  233. * @return void
  234. */
  235. public function testInitNoImportNoFieldsException()
  236. {
  237. $this->expectException(\Cake\Core\Exception\Exception::class);
  238. $this->expectExceptionMessage('Cannot describe schema for table `letters` for fixture `Cake\Test\TestCase\TestSuite\LettersFixture` : the table does not exist.');
  239. $fixture = new LettersFixture();
  240. $fixture->init();
  241. }
  242. /**
  243. * test schema reflection without $import or $fields will reflect the schema
  244. *
  245. * @return void
  246. */
  247. public function testInitNoImportNoFields()
  248. {
  249. $db = ConnectionManager::get('test');
  250. $table = new Table('letters', [
  251. 'id' => ['type' => 'integer'],
  252. 'letter' => ['type' => 'string', 'length' => 1]
  253. ]);
  254. $table->addConstraint('primary', ['type' => 'primary', 'columns' => ['id']]);
  255. $sql = $table->createSql($db);
  256. foreach ($sql as $stmt) {
  257. $db->execute($stmt);
  258. }
  259. $fixture = new LettersFixture();
  260. $fixture->init();
  261. $this->assertEquals(['id', 'letter'], $fixture->schema()->columns());
  262. $db = $this->getMockBuilder('Cake\Database\Connection')
  263. ->setMethods(['prepare', 'execute'])
  264. ->disableOriginalConstructor()
  265. ->getMock();
  266. $db->expects($this->never())
  267. ->method('prepare');
  268. $db->expects($this->never())
  269. ->method('execute');
  270. $this->assertTrue($fixture->create($db));
  271. $this->assertTrue($fixture->drop($db));
  272. // Cleanup.
  273. $db = ConnectionManager::get('test');
  274. $db->execute('DROP TABLE letters');
  275. }
  276. /**
  277. * test create method
  278. *
  279. * @return void
  280. */
  281. public function testCreate()
  282. {
  283. $fixture = new ArticlesFixture();
  284. $db = $this->getMockBuilder('Cake\Database\Connection')
  285. ->disableOriginalConstructor()
  286. ->getMock();
  287. $table = $this->getMockBuilder('Cake\Database\Schema\Table')
  288. ->setConstructorArgs(['articles'])
  289. ->getMock();
  290. $table->expects($this->once())
  291. ->method('createSql')
  292. ->with($db)
  293. ->will($this->returnValue(['sql', 'sql']));
  294. $fixture->schema($table);
  295. $statement = $this->getMockBuilder('\PDOStatement')
  296. ->setMethods(['execute', 'closeCursor'])
  297. ->getMock();
  298. $statement->expects($this->atLeastOnce())->method('closeCursor');
  299. $statement->expects($this->atLeastOnce())->method('execute');
  300. $db->expects($this->exactly(2))
  301. ->method('prepare')
  302. ->will($this->returnValue($statement));
  303. $this->assertTrue($fixture->create($db));
  304. }
  305. /**
  306. * test create method, trigger error
  307. *
  308. * @return void
  309. */
  310. public function testCreateError()
  311. {
  312. $this->expectException(\PHPUnit\Framework\Error\Error::class);
  313. $fixture = new ArticlesFixture();
  314. $db = $this->getMockBuilder('Cake\Database\Connection')
  315. ->disableOriginalConstructor()
  316. ->getMock();
  317. $table = $this->getMockBuilder('Cake\Database\Schema\Table')
  318. ->setConstructorArgs(['articles'])
  319. ->getMock();
  320. $table->expects($this->once())
  321. ->method('createSql')
  322. ->with($db)
  323. ->will($this->throwException(new Exception('oh noes')));
  324. $fixture->schema($table);
  325. $fixture->create($db);
  326. }
  327. /**
  328. * test the insert method
  329. *
  330. * @return void
  331. */
  332. public function testInsert()
  333. {
  334. $fixture = new ArticlesFixture();
  335. $db = $this->getMockBuilder('Cake\Database\Connection')
  336. ->disableOriginalConstructor()
  337. ->getMock();
  338. $query = $this->getMockBuilder('Cake\Database\Query')
  339. ->setConstructorArgs([$db])
  340. ->getMock();
  341. $db->expects($this->once())
  342. ->method('newQuery')
  343. ->will($this->returnValue($query));
  344. $query->expects($this->once())
  345. ->method('insert')
  346. ->with(['name', 'created'], ['name' => 'string', 'created' => 'datetime'])
  347. ->will($this->returnSelf());
  348. $query->expects($this->once())
  349. ->method('into')
  350. ->with('articles')
  351. ->will($this->returnSelf());
  352. $expected = [
  353. ['name' => 'Gandalf', 'created' => '2009-04-28 19:20:00'],
  354. ['name' => 'Captain Picard', 'created' => '2009-04-28 19:20:00'],
  355. ['name' => 'Chewbacca', 'created' => '2009-04-28 19:20:00']
  356. ];
  357. $query->expects($this->at(2))
  358. ->method('values')
  359. ->with($expected[0])
  360. ->will($this->returnSelf());
  361. $query->expects($this->at(3))
  362. ->method('values')
  363. ->with($expected[1])
  364. ->will($this->returnSelf());
  365. $query->expects($this->at(4))
  366. ->method('values')
  367. ->with($expected[2])
  368. ->will($this->returnSelf());
  369. $statement = $this->getMockBuilder('\PDOStatement')
  370. ->setMethods(['closeCursor'])
  371. ->getMock();
  372. $statement->expects($this->once())->method('closeCursor');
  373. $query->expects($this->once())
  374. ->method('execute')
  375. ->will($this->returnValue($statement));
  376. $this->assertSame($statement, $fixture->insert($db));
  377. }
  378. /**
  379. * test the insert method
  380. *
  381. * @return void
  382. */
  383. public function testInsertImport()
  384. {
  385. $fixture = new ImportsFixture();
  386. $db = $this->getMockBuilder('Cake\Database\Connection')
  387. ->disableOriginalConstructor()
  388. ->getMock();
  389. $query = $this->getMockBuilder('Cake\Database\Query')
  390. ->setConstructorArgs([$db])
  391. ->getMock();
  392. $db->expects($this->once())
  393. ->method('newQuery')
  394. ->will($this->returnValue($query));
  395. $query->expects($this->once())
  396. ->method('insert')
  397. ->with(['title', 'body'], ['title' => 'string', 'body' => 'text'])
  398. ->will($this->returnSelf());
  399. $query->expects($this->once())
  400. ->method('into')
  401. ->with('posts')
  402. ->will($this->returnSelf());
  403. $expected = [
  404. ['title' => 'Hello!', 'body' => 'Hello world!'],
  405. ];
  406. $query->expects($this->at(2))
  407. ->method('values')
  408. ->with($expected[0])
  409. ->will($this->returnSelf());
  410. $statement = $this->getMockBuilder('\PDOStatement')
  411. ->setMethods(['closeCursor'])
  412. ->getMock();
  413. $statement->expects($this->once())->method('closeCursor');
  414. $query->expects($this->once())
  415. ->method('execute')
  416. ->will($this->returnValue($statement));
  417. $this->assertSame($statement, $fixture->insert($db));
  418. }
  419. /**
  420. * test the insert method
  421. *
  422. * @return void
  423. */
  424. public function testInsertStrings()
  425. {
  426. $fixture = new StringsTestsFixture();
  427. $db = $this->getMockBuilder('Cake\Database\Connection')
  428. ->disableOriginalConstructor()
  429. ->getMock();
  430. $query = $this->getMockBuilder('Cake\Database\Query')
  431. ->setConstructorArgs([$db])
  432. ->getMock();
  433. $db->expects($this->once())
  434. ->method('newQuery')
  435. ->will($this->returnValue($query));
  436. $query->expects($this->once())
  437. ->method('insert')
  438. ->with(['name', 'email', 'age'], ['name' => 'string', 'email' => 'string', 'age' => 'integer'])
  439. ->will($this->returnSelf());
  440. $query->expects($this->once())
  441. ->method('into')
  442. ->with('strings')
  443. ->will($this->returnSelf());
  444. $expected = [
  445. ['name' => 'Mark Doe', 'email' => 'mark.doe@email.com', 'age' => null],
  446. ['name' => 'John Doe', 'email' => 'john.doe@email.com', 'age' => 20],
  447. ['name' => 'Jane Doe', 'email' => 'jane.doe@email.com', 'age' => 30],
  448. ];
  449. $query->expects($this->at(2))
  450. ->method('values')
  451. ->with($expected[0])
  452. ->will($this->returnSelf());
  453. $query->expects($this->at(3))
  454. ->method('values')
  455. ->with($expected[1])
  456. ->will($this->returnSelf());
  457. $query->expects($this->at(4))
  458. ->method('values')
  459. ->with($expected[2])
  460. ->will($this->returnSelf());
  461. $statement = $this->getMockBuilder('\PDOStatement')
  462. ->setMethods(['closeCursor'])
  463. ->getMock();
  464. $statement->expects($this->once())->method('closeCursor');
  465. $query->expects($this->once())
  466. ->method('execute')
  467. ->will($this->returnValue($statement));
  468. $this->assertSame($statement, $fixture->insert($db));
  469. }
  470. /**
  471. * Test the drop method
  472. *
  473. * @return void
  474. */
  475. public function testDrop()
  476. {
  477. $fixture = new ArticlesFixture();
  478. $db = $this->getMockBuilder('Cake\Database\Connection')
  479. ->disableOriginalConstructor()
  480. ->getMock();
  481. $statement = $this->getMockBuilder('\PDOStatement')
  482. ->setMethods(['closeCursor'])
  483. ->getMock();
  484. $statement->expects($this->once())->method('closeCursor');
  485. $db->expects($this->once())->method('execute')
  486. ->with('sql')
  487. ->will($this->returnValue($statement));
  488. $table = $this->getMockBuilder('Cake\Database\Schema\Table')
  489. ->setConstructorArgs(['articles'])
  490. ->getMock();
  491. $table->expects($this->once())
  492. ->method('dropSql')
  493. ->with($db)
  494. ->will($this->returnValue(['sql']));
  495. $fixture->schema($table);
  496. $this->assertTrue($fixture->drop($db));
  497. }
  498. /**
  499. * Test the truncate method.
  500. *
  501. * @return void
  502. */
  503. public function testTruncate()
  504. {
  505. $fixture = new ArticlesFixture();
  506. $db = $this->getMockBuilder('Cake\Database\Connection')
  507. ->disableOriginalConstructor()
  508. ->getMock();
  509. $statement = $this->getMockBuilder('\PDOStatement')
  510. ->setMethods(['closeCursor'])
  511. ->getMock();
  512. $statement->expects($this->once())->method('closeCursor');
  513. $db->expects($this->once())->method('execute')
  514. ->with('sql')
  515. ->will($this->returnValue($statement));
  516. $table = $this->getMockBuilder('Cake\Database\Schema\Table')
  517. ->setConstructorArgs(['articles'])
  518. ->getMock();
  519. $table->expects($this->once())
  520. ->method('truncateSql')
  521. ->with($db)
  522. ->will($this->returnValue(['sql']));
  523. $fixture->schema($table);
  524. $this->assertTrue($fixture->truncate($db));
  525. }
  526. }