‪TYPO3CMS  10.4
ConnectionTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Configuration;
21 use Doctrine\DBAL\Driver\Mysqli\Driver;
22 use Doctrine\DBAL\Driver\Mysqli\MysqliConnection;
23 use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
24 use Doctrine\DBAL\Platforms\MySqlPlatform;
25 use Doctrine\DBAL\Statement;
26 use Doctrine\DBAL\VersionAwarePlatformDriver;
27 use Prophecy\Prophecy\ObjectProphecy;
33 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
34 
38 class ‪ConnectionTest extends UnitTestCase
39 {
43  protected ‪$connection;
44 
48  protected ‪$platform;
49 
53  protected ‪$testTable = 'testTable';
54 
58  protected function ‪setUp(): void
59  {
60  parent::setUp();
61 
62  $this->connection = $this->getMockBuilder(Connection::class)
63  ->setMethods(
64  [
65  'connect',
66  'executeQuery',
67  'executeUpdate',
68  'executeStatement',
69  'getDatabasePlatform',
70  'getDriver',
71  'getExpressionBuilder',
72  'getWrappedConnection',
73  ]
74  )
75  ->setConstructorArgs([['platform' => $this->prophesize(MySqlPlatform::class)->reveal()], $this->prophesize(Driver::class)->reveal(), new Configuration(), null])
76  ->getMock();
77 
78  $this->connection->expects(self::any())
79  ->method('getExpressionBuilder')
80  ->willReturn(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection));
81 
82  $this->connection->expects(self::any())
83  ->method('connect');
84 
85  $this->connection->expects(self::any())
86  ->method('getDatabasePlatform')
87  ->willReturn(new ‪MockPlatform());
88  }
89 
94  {
95  self::assertInstanceOf(QueryBuilder::class, $this->connection->createQueryBuilder());
96  }
97 
101  public function ‪quoteIdentifierDataProvider()
102  {
103  return [
104  'SQL star' => [
105  '*',
106  '*',
107  ],
108  'fieldname' => [
109  'aField',
110  '"aField"',
111  ],
112  'whitespace' => [
113  'with blanks',
114  '"with blanks"',
115  ],
116  'double quotes' => [
117  '"double" quotes',
118  '"""double"" quotes"',
119  ],
120  'single quotes' => [
121  "'single'",
122  '"\'single\'"',
123 
124  ],
125  'multiple double quotes' => [
126  '""multiple""',
127  '"""""multiple"""""',
128  ],
129  'multiple single quotes' => [
130  "''multiple''",
131  '"\'\'multiple\'\'"',
132  ],
133  'backticks' => [
134  '`backticks`',
135  '"`backticks`"',
136  ],
137  'slashes' => [
138  '/slashes/',
139  '"/slashes/"',
140  ],
141  'backslashes' => [
142  '\\backslashes\\',
143  '"\\backslashes\\"',
144  ],
145  ];
146  }
147 
154  public function ‪quoteIdentifier(string $input, string $expected)
155  {
156  self::assertSame($expected, $this->connection->quoteIdentifier($input));
157  }
158 
162  public function ‪quoteIdentifiers()
163  {
164  $input = [
165  'aField',
166  'anotherField',
167  ];
168 
169  $expected = [
170  '"aField"',
171  '"anotherField"',
172  ];
173 
174  self::assertSame($expected, $this->connection->quoteIdentifiers($input));
175  }
176 
180  public function ‪insertQueriesDataProvider()
181  {
182  return [
183  'single value' => [
184  ['aTestTable', ['aField' => 'aValue']],
185  'INSERT INTO "aTestTable" ("aField") VALUES (?)',
186  ['aValue'],
187  [],
188  ],
189  'multiple values' => [
190  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
191  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
192  ['aValue', 'bValue'],
193  [],
194  ],
195  'with types' => [
196  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], [‪Connection::PARAM_STR, ‪Connection::PARAM_STR]],
197  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
198  ['aValue', 'bValue'],
200  ],
201  'with types for field' => [
202  [
203  'aTestTable',
204  ['aField' => 123, 'bField' => 'bValue'],
205  ['aField' => ‪Connection::PARAM_INT, 'bField' => ‪Connection::PARAM_LOB]
206  ],
207  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
208  [123, 'bValue'],
210  ],
211  ];
212  }
213 
222  public function ‪insertQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes)
223  {
224 
225  // @todo drop else branch and condition once doctrine/dbal is requried in version 2.11.0 minimum
226  if (method_exists(Connection::class, 'executeStatement')) {
227  $this->connection->expects(self::once())
228  ->method('executeStatement')
229  ->with($expectedQuery, $expectedValues, $expectedTypes)
230  ->willReturn(1);
231  } else {
232  $this->connection->expects(self::once())
233  ->method('executeUpdate')
234  ->with($expectedQuery, $expectedValues, $expectedTypes)
235  ->willReturn(1);
236  }
237 
238  $this->connection->insert(...‪$args);
239  }
240 
244  public function ‪bulkInsert()
245  {
246  $this->connection->expects(self::once())
247  ->method('executeUpdate')
248  ->with('INSERT INTO "aTestTable" ("aField") VALUES (?), (?)', ['aValue', 'anotherValue'])
249  ->willReturn(2);
250 
251  $this->connection->bulkInsert('aTestTable', [['aField' => 'aValue'], ['aField' => 'anotherValue']], ['aField']);
252  }
253 
257  public function ‪updateQueriesDataProvider()
258  {
259  return [
260  'single value' => [
261  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1]],
262  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
263  ['aValue', 1],
264  [],
265  ],
266  'multiple values' => [
267  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], ['uid' => 1]],
268  'UPDATE "aTestTable" SET "aField" = ?, "bField" = ? WHERE "uid" = ?',
269  ['aValue', 'bValue', 1],
270  [],
271  ],
272  'with types' => [
273  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], [‪Connection::PARAM_STR]],
274  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
275  ['aValue', 1],
277  ],
278  'with types for field' => [
279  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], ['aField' => ‪Connection::PARAM_LOB]],
280  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
281  ['aValue', 1],
283  ],
284  ];
285  }
286 
295  public function ‪updateQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes)
296  {
297  // @todo drop else branch and condition once doctrine/dbal is requried in version 2.11.0 minimum
298  if (method_exists(Connection::class, 'executeStatement')) {
299  $this->connection->expects(self::once())
300  ->method('executeStatement')
301  ->with($expectedQuery, $expectedValues, $expectedTypes)
302  ->willReturn(1);
303  } else {
304  $this->connection->expects(self::once())
305  ->method('executeUpdate')
306  ->with($expectedQuery, $expectedValues, $expectedTypes)
307  ->willReturn(1);
308  }
309 
310  $this->connection->update(...‪$args);
311  }
312 
316  public function ‪deleteQueriesDataProvider()
317  {
318  return [
319  'single condition' => [
320  ['aTestTable', ['aField' => 'aValue']],
321  'DELETE FROM "aTestTable" WHERE "aField" = ?',
322  ['aValue'],
323  [],
324  ],
325  'multiple conditions' => [
326  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
327  'DELETE FROM "aTestTable" WHERE "aField" = ? AND "bField" = ?',
328  ['aValue', 'bValue'],
329  [],
330  ],
331  'with types' => [
332  ['aTestTable', ['aField' => 'aValue'], [‪Connection::PARAM_STR]],
333  'DELETE FROM "aTestTable" WHERE "aField" = ?',
334  ['aValue'],
336  ],
337  'with types for field' => [
338  ['aTestTable', ['aField' => 'aValue'], ['aField' => ‪Connection::PARAM_STR]],
339  'DELETE FROM "aTestTable" WHERE "aField" = ?',
340  ['aValue'],
342  ],
343  ];
344  }
345 
354  public function ‪deleteQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes)
355  {
356  // @todo drop else branch and condition once doctrine/dbal is requried in version 2.11.0 minimum
357  if (method_exists(Connection::class, 'executeStatement')) {
358  $this->connection->expects(self::once())
359  ->method('executeStatement')
360  ->with($expectedQuery, $expectedValues, $expectedTypes)
361  ->willReturn(1);
362  } else {
363  $this->connection->expects(self::once())
364  ->method('executeUpdate')
365  ->with($expectedQuery, $expectedValues, $expectedTypes)
366  ->willReturn(1);
367  }
368 
369  $this->connection->delete(...‪$args);
370  }
371 
382  public function ‪selectQueriesDataProvider()
383  {
384  return [
385  'all columns' => [
386  [['*'], 'aTable'],
387  'SELECT * FROM "aTable"',
388  [],
389  ],
390  'subset of columns' => [
391  [['aField', 'anotherField'], 'aTable'],
392  'SELECT "aField", "anotherField" FROM "aTable"',
393  [],
394  ],
395  'conditions' => [
396  [['*'], 'aTable', ['aField' => 'aValue']],
397  'SELECT * FROM "aTable" WHERE "aField" = :dcValue1',
398  ['dcValue1' => 'aValue'],
399  ],
400  'grouping' => [
401  [['*'], 'aTable', [], ['aField']],
402  'SELECT * FROM "aTable" GROUP BY "aField"',
403  [],
404  ],
405  'ordering' => [
406  [['*'], 'aTable', [], [], ['aField' => 'ASC']],
407  'SELECT * FROM "aTable" ORDER BY "aField" ASC',
408  [],
409  ],
410  'limit' => [
411  [['*'], 'aTable', [], [], [], 1],
412  'SELECT * FROM "aTable" LIMIT 1',
413  [],
414  ],
415  'offset' => [
416  [['*'], 'aTable', [], [], [], 1, 10],
417  'SELECT * FROM "aTable" LIMIT 1 OFFSET 10',
418  [],
419  ],
420  'everything' => [
421  [
422  ['aField', 'anotherField'],
423  'aTable',
424  ['aField' => 'aValue'],
425  ['anotherField'],
426  ['aField' => 'ASC'],
427  1,
428  10,
429  ],
430  'SELECT "aField", "anotherField" FROM "aTable" WHERE "aField" = :dcValue1 ' .
431  'GROUP BY "anotherField" ORDER BY "aField" ASC LIMIT 1 OFFSET 10',
432  ['dcValue1' => 'aValue'],
433  ],
434  ];
435  }
436 
444  public function ‪selectQueries(array ‪$args, string $expectedQuery, array $expectedParameters)
445  {
446  $resultStatement = $this->createMock(Statement::class);
447 
448  $this->connection->expects(self::once())
449  ->method('executeQuery')
450  ->with($expectedQuery, $expectedParameters)
451  ->willReturn($resultStatement);
452 
453  $this->connection->select(...‪$args);
454  }
455 
466  public function ‪countQueriesDataProvider()
467  {
468  return [
469  'all columns' => [
470  ['*', 'aTable', []],
471  'SELECT COUNT(*) FROM "aTable"',
472  [],
473  ],
474  'specified columns' => [
475  ['aField', 'aTable', []],
476  'SELECT COUNT("aField") FROM "aTable"',
477  [],
478  ],
479  'conditions' => [
480  ['aTable.aField', 'aTable', ['aField' => 'aValue']],
481  'SELECT COUNT("aTable"."aField") FROM "aTable" WHERE "aField" = :dcValue1',
482  ['dcValue1' => 'aValue'],
483  ],
484  ];
485  }
486 
494  public function ‪countQueries(array ‪$args, string $expectedQuery, array $expectedParameters)
495  {
496  $resultStatement = $this->createMock(Statement::class);
497 
498  $resultStatement->expects(self::once())
499  ->method('fetchColumn')
500  ->with(0)
501  ->willReturn(0);
502 
503  $this->connection->expects(self::once())
504  ->method('executeQuery')
505  ->with($expectedQuery, $expectedParameters)
506  ->willReturn($resultStatement);
507 
508  $this->connection->count(...‪$args);
509  }
510 
514  public function ‪truncateQuery()
515  {
516  $this->connection->expects(self::once())
517  ->method('executeUpdate')
518  ->with('TRUNCATE "aTestTable"')
519  ->willReturn(0);
520 
521  $this->connection->truncate('aTestTable', false);
522  }
523 
528  {
530  $driverProphet = $this->prophesize(Driver::class);
531  $driverProphet->willImplement(VersionAwarePlatformDriver::class);
532 
534  $wrappedConnectionProphet = $this->prophesize(MysqliConnection::class);
535  $wrappedConnectionProphet->willImplement(ServerInfoAwareConnection::class);
536  $wrappedConnectionProphet->requiresQueryForServerVersion()->willReturn(false);
537  $wrappedConnectionProphet->getServerVersion()->willReturn('5.7.11');
538 
539  $this->connection->expects(self::any())
540  ->method('getDriver')
541  ->willReturn($driverProphet->reveal());
542  $this->connection->expects(self::any())
543  ->method('getWrappedConnection')
544  ->willReturn($wrappedConnectionProphet->reveal());
545 
546  self::assertSame('mock 5.7.11', $this->connection->getServerVersion());
547  }
548 }
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\updateQueries
‪updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:292
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:47
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:35
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\setUp
‪setUp()
Definition: ConnectionTest.php:55
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\countQueriesDataProvider
‪array countQueriesDataProvider()
Definition: ConnectionTest.php:463
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\updateQueriesDataProvider
‪array updateQueriesDataProvider()
Definition: ConnectionTest.php:254
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\createQueryBuilderReturnsInstanceOfTypo3QueryBuilder
‪createQueryBuilderReturnsInstanceOfTypo3QueryBuilder()
Definition: ConnectionTest.php:90
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:52
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\insertQueries
‪insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:219
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\getServerVersionReportsPlatformVersion
‪getServerVersionReportsPlatformVersion()
Definition: ConnectionTest.php:524
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\countQueries
‪countQueries(array $args, string $expectedQuery, array $expectedParameters)
Definition: ConnectionTest.php:491
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\selectQueriesDataProvider
‪array selectQueriesDataProvider()
Definition: ConnectionTest.php:379
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifier
‪quoteIdentifier(string $input, string $expected)
Definition: ConnectionTest.php:151
‪TYPO3\CMS\Core\Tests\Unit\Database
Definition: ConnectionPoolTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform
Definition: MockPlatform.php:22
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\deleteQueries
‪deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:351
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest
Definition: ConnectionTest.php:39
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\selectQueries
‪selectQueries(array $args, string $expectedQuery, array $expectedParameters)
Definition: ConnectionTest.php:441
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\bulkInsert
‪bulkInsert()
Definition: ConnectionTest.php:241
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\truncateQuery
‪truncateQuery()
Definition: ConnectionTest.php:511
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$connection
‪Connection PHPUnit Framework MockObject MockObject $connection
Definition: ConnectionTest.php:42
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\deleteQueriesDataProvider
‪array deleteQueriesDataProvider()
Definition: ConnectionTest.php:313
‪$args
‪$args
Definition: validateRstFiles.php:214
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$testTable
‪string $testTable
Definition: ConnectionTest.php:50
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifiers
‪quoteIdentifiers()
Definition: ConnectionTest.php:159
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\insertQueriesDataProvider
‪array insertQueriesDataProvider()
Definition: ConnectionTest.php:177
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$platform
‪Doctrine DBAL Platforms AbstractPlatform $platform
Definition: ConnectionTest.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifierDataProvider
‪array quoteIdentifierDataProvider()
Definition: ConnectionTest.php:98
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:57