Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
SchemaBuilderTest.php
Go to the documentation of this file.
1 <?php
8 
21 
29 class SchemaBuilderTest extends \PHPUnit\Framework\TestCase
30 {
34  private $model;
35 
39  private $objectManagerHelper;
40 
44  private $elementFactoryMock;
45 
49  private $dbSchemaReaderMock;
50 
54  private $shardingMock;
55 
56  protected function setUp()
57  {
58  $this->elementFactoryMock = $this->getMockBuilder(ElementFactory::class)
59  ->disableOriginalConstructor()
60  ->getMock();
61  $this->dbSchemaReaderMock = $this->getMockBuilder(DbSchemaReaderInterface::class)
62  ->getMockForAbstractClass();
63  $this->shardingMock = $this->getMockBuilder(Sharding::class)
64  ->disableOriginalConstructor()
65  ->getMock();
66 
67  $this->objectManagerHelper = new ObjectManagerHelper($this);
68  $this->model = $this->objectManagerHelper->getObject(
69  \Magento\Framework\Setup\Declaration\Schema\Db\SchemaBuilder::class,
70  [
71  'elementFactory' => $this->elementFactoryMock,
72  'dbSchemaReader' => $this->dbSchemaReaderMock,
73  'sharding' => $this->shardingMock
74  ]
75  );
76  }
77 
82  public function dataProvider()
83  {
84  return [
85  [
86  'columns' => [
87  'first_table' => [
88  'first_column' => [
89  'name' => 'first_column',
90  'type' => 'int',
91  'padding' => 10,
92  'identity' => true,
93  'nullable' => false
94  ],
95  'foreign_column' => [
96  'name' => 'foreign_column',
97  'type' => 'int',
98  'padding' => 10,
99  'nullable' => false
100  ],
101  'second_column' => [
102  'name' => 'second_column',
103  'type' => 'timestamp',
104  'default' => 'CURRENT_TIMESTAMP',
105  'on_update' => true
106  ],
107  ],
108  'second_table' => [
109  'ref_column' => [
110  'name' => 'ref_column',
111  'type' => 'int',
112  'padding' => 10,
113  'nullable' => false
114  ],
115  ]
116  ],
117  'references' => [
118  'first_table' => [
119  'some_foreign_key' => [
120  'name' => 'some_foreign_key',
121  'type' => 'foreign',
122  'column' => 'foreign_column',
123  'table' => 'first_table',
124  'referenceTable' => 'second_table',
125  'referenceColumn' => 'ref_column'
126  ],
127  ]
128  ],
129  'constraints' => [
130  'first_table' => [
131  'PRIMARY' => [
132  'name' => 'PRIMARY',
133  'type' => 'primary',
134  'column' => [
135  'first_column'
136  ],
137  'nameWithoutPrefix' => 'PRIMARY',
138  ]
139  ]
140  ],
141  'indexes' => [
142  'second_table' => [
143  'FIRST_INDEX' => [
144  'name' => 'FIRST_INDEX',
145  'nameWithoutPrefix' => 'FIRST_INDEX',
146  'column' => [
147  'ref_column'
148  ],
149  ]
150  ]
151  ]
152  ]
153  ];
154  }
155 
162  private function createTable($name)
163  {
164  return new Table(
165  $name,
166  $name,
167  'table',
168  'default',
169  'resource',
170  'utf-8',
171  'utf-8',
172  ''
173  );
174  }
175 
183  private function createIntegerAIColumn($name, Table $table)
184  {
185  return new Integer(
186  $name,
187  'int',
188  $table,
189  10,
190  true,
191  false,
192  true
193  );
194  }
195 
203  private function createIntegerColumn($name, Table $table)
204  {
205  return new Integer(
206  $name,
207  'int',
208  $table,
209  10
210  );
211  }
212 
220  private function createPrimaryConstraint(Table $table, array $columns)
221  {
222  return new Internal(
223  'PRIMARY',
224  'primary',
225  $table,
226  'PRIMARY',
227  $columns
228  );
229  }
230 
239  private function createIndex($indexName, Table $table, array $columns)
240  {
241  return new Index(
242  $indexName,
243  'index',
244  $table,
245  $columns,
246  'btree',
247  $indexName
248  );
249  }
250 
258  private function createTimestampColumn($name, Table $table)
259  {
260  return new Timestamp(
261  $name,
262  'timestamp',
263  $table,
264  'CURRENT_TIMESTAMP',
265  false,
266  true
267  );
268  }
269 
277  public function testBuild(array $columns, array $references, array $constraints, array $indexes)
278  {
279  $this->prepareSchemaMocks($columns, $references, $constraints, $indexes);
280  $resourceConnectionMock = $this->getMockBuilder(ResourceConnection::class)
281  ->disableOriginalConstructor()
282  ->getMock();
283  $resourceConnectionMock->expects(self::any())
284  ->method('getTableName')
285  ->willReturnArgument(0);
287  $schema = $this->objectManagerHelper->getObject(
288  Schema::class,
289  ['resourceConnection' => $resourceConnectionMock]
290  );
291  $this->model->build($schema);
292  }
293 
303  public function testBuildUnknownIndexColumn(array $columns, array $references, array $constraints, array $indexes)
304  {
305  $indexes['second_table']['FIRST_INDEX']['column'][] = 'unknown_column';
306  $this->prepareSchemaMocks($columns, $references, $constraints, $indexes);
307  $resourceConnectionMock = $this->getMockBuilder(ResourceConnection::class)
308  ->disableOriginalConstructor()
309  ->getMock();
311  $schema = $this->objectManagerHelper->getObject(
312  Schema::class,
313  ['resourceConnection' => $resourceConnectionMock]
314  );
315  $this->expectException(\Exception::class);
316  $this->expectExceptionMessage(
317  'User Warning: Column unknown_column does not exist for index/constraint FIRST_INDEX in table second_table.'
318  );
319  $this->model->build($schema);
320  }
321 
331  private function prepareSchemaMocks(array $columns, array $references, array $constraints, array $indexes)
332  {
333  $withContext = [['first_table', 'default'], ['second_table', 'default']];
334  $this->shardingMock->expects(self::once())
335  ->method('getResources')
336  ->willReturn(['default']);
337  $this->dbSchemaReaderMock->expects(self::once())
338  ->method('readTables')
339  ->with('default')
340  ->willReturn(['first_table', 'second_table']);
341  $this->dbSchemaReaderMock->expects($this->any())
342  ->method('getTableOptions')
343  ->withConsecutive(...array_values($withContext))
344  ->willReturnOnConsecutiveCalls(
345  ['engine' => 'innodb', 'comment' => '', 'charset' => 'utf-8', 'collation' => 'utf-8'],
346  ['engine' => 'innodb', 'comment' => 'Not null comment', 'charset' => 'utf-8', 'collation' => 'utf-8']
347  );
348  $this->dbSchemaReaderMock->expects($this->any())
349  ->method('readColumns')
350  ->withConsecutive(...array_values($withContext))
351  ->willReturnOnConsecutiveCalls($columns['first_table'], $columns['second_table']);
352  $this->dbSchemaReaderMock->expects($this->any())
353  ->method('readIndexes')
354  ->withConsecutive(...array_values($withContext))
355  ->willReturnOnConsecutiveCalls([], $indexes['second_table']);
356  $this->dbSchemaReaderMock->expects($this->any())
357  ->method('readConstraints')
358  ->withConsecutive(...array_values($withContext))
359  ->willReturnOnConsecutiveCalls($constraints['first_table'], []);
360  $this->dbSchemaReaderMock->expects($this->any())
361  ->method('readReferences')
362  ->withConsecutive(...array_values($withContext))
363  ->willReturnOnConsecutiveCalls($references['first_table'], []);
364  $table = $this->createTable('first_table');
365  $refTable = $this->createTable('second_table');
366  $refColumn = $this->createIntegerColumn('ref_column', $refTable);
367  $index = $this->createIndex('FIRST_INDEX', $table, [$refColumn]);
368  $refTable->addColumns([$refColumn]);
369  $refTable->addIndexes([$index]);
370  $firstColumn = $this->createIntegerAIColumn('first_column', $table);
371  $foreignColumn = $this->createIntegerColumn('foreign_column', $table);
372  $timestampColumn = $this->createTimestampColumn('second_column', $table);
373  $primaryKey = $this->createPrimaryConstraint($table, [$firstColumn]);
374  $foreignKey = new Reference(
375  'some_foreign_key',
376  'foreign',
377  $table,
378  'some_foreign_key',
379  $foreignColumn,
380  $refTable,
381  $refColumn,
382  'CASCADE'
383  );
384  $table->addColumns([$firstColumn, $foreignColumn, $timestampColumn]);
385  $table->addConstraints([$foreignKey, $primaryKey]);
386  $this->elementFactoryMock->expects($this->any())
387  ->method('create')
388  ->withConsecutive(
389  [
390  'table',
391  [
392  'name' =>'first_table',
393  'resource' => 'default',
394  'engine' => 'innodb',
395  'comment' => null,
396  'charset' => 'utf-8',
397  'collation' => 'utf-8'
398  ]
399  ],
400  [
401  'int',
402  [
403  'name' => 'first_column',
404  'type' => 'int',
405  'table' => $table,
406  'padding' => 10,
407  'identity' => true,
408  'nullable' => false,
409  ]
410  ],
411  [
412  'int',
413  [
414  'name' => 'foreign_column',
415  'type' => 'int',
416  'table' => $table,
417  'padding' => 10,
418  'nullable' => false,
419  ]
420  ],
421  [
422  'timestamp',
423  [
424  'name' => 'second_column',
425  'type' => 'timestamp',
426  'table' => $table,
427  'default' => 'CURRENT_TIMESTAMP',
428  'on_update' => true,
429  ]
430  ],
431  [
432  'primary',
433  [
434  'name' => 'PRIMARY',
435  'type' => 'primary',
436  'columns' => [$firstColumn],
437  'table' => $table,
438  'nameWithoutPrefix' => 'PRIMARY',
439  'column' => ['first_column'],
440  ]
441  ],
442  [
443  'table',
444  [
445  'name' =>'second_table',
446  'resource' => 'default',
447  'engine' => 'innodb',
448  'comment' => 'Not null comment',
449  'charset' => 'utf-8',
450  'collation' => 'utf-8'
451  ]
452  ],
453  [
454  'int',
455  [
456  'name' => 'ref_column',
457  'type' => 'int',
458  'table' => $refTable,
459  'padding' => 10,
460  'nullable' => false,
461  ]
462  ],
463  [
464  'index',
465  [
466  'name' => 'FIRST_INDEX',
467  'table' => $refTable,
468  'column' => ['ref_column'],
469  'columns' => [$refColumn],
470  'nameWithoutPrefix' => 'FIRST_INDEX',
471  ]
472  ],
473  [
474  'foreign',
475  [
476  'name' => 'some_foreign_key',
477  'type' => 'foreign',
478  'column' => $foreignColumn,
479  'table' => $table,
480  'referenceTable' => $refTable,
481  'referenceColumn' => $refColumn,
482  ]
483  ]
484  )
485  ->willReturnOnConsecutiveCalls(
486  $table,
487  $firstColumn,
488  $foreignColumn,
489  $timestampColumn,
490  $primaryKey,
491  $refTable,
492  $refColumn,
493  $index,
494  $foreignKey
495  );
496  }
497 }
return false
Definition: gallery.phtml:36
$columns
Definition: default.phtml:15
$table
Definition: trigger.php:14
$index
Definition: list.phtml:44
if(!isset($_GET['name'])) $name
Definition: log.php:14