‪TYPO3CMS  ‪main
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\AbstractMySQLDriver;
22 use Doctrine\DBAL\Platforms\AbstractPlatform;
23 use Doctrine\DBAL\Platforms\MySQLPlatform;
24 use Doctrine\DBAL\Result;
25 use PHPUnit\Framework\MockObject\MockObject;
28 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32 
33 final class ‪ConnectionTest extends UnitTestCase
34 {
35  protected ‪Connection&MockObject ‪$connection;
36 
37  protected ?AbstractPlatform ‪$platform;
38  protected string ‪$testTable = 'testTable';
39 
43  protected function ‪setUp(): void
44  {
45  parent::setUp();
46 
47  $this->connection = $this->getMockBuilder(Connection::class)
48  ->onlyMethods(
49  [
50  'connect',
51  'ensureDatabaseValueTypes',
52  'executeQuery',
53  'executeUpdate',
54  'executeStatement',
55  'getDatabasePlatform',
56  'getDriver',
57  'getExpressionBuilder',
58  'getWrappedConnection',
59  ]
60  )
61  ->setConstructorArgs([['platform' => $this->createMock(MySQLPlatform::class)], $this->createMock(AbstractMySQLDriver::class), new Configuration(), null])
62  ->getMock();
63 
64  $this->connection
65  ->method('getExpressionBuilder')
66  ->willReturn(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection));
67 
68  $this->connection
69  ->method('connect');
70 
71  $this->connection
72  ->method('getDatabasePlatform')
73  ->willReturn(new ‪MockPlatform());
74  }
75 
80  {
81  self::assertInstanceOf(QueryBuilder::class, $this->connection->createQueryBuilder());
82  }
83 
84  public static function ‪quoteIdentifierDataProvider(): array
85  {
86  return [
87  'SQL star' => [
88  '*',
89  '*',
90  ],
91  'fieldname' => [
92  'aField',
93  '"aField"',
94  ],
95  'whitespace' => [
96  'with blanks',
97  '"with blanks"',
98  ],
99  'double quotes' => [
100  '"double" quotes',
101  '"""double"" quotes"',
102  ],
103  'single quotes' => [
104  "'single'",
105  '"\'single\'"',
106 
107  ],
108  'multiple double quotes' => [
109  '""multiple""',
110  '"""""multiple"""""',
111  ],
112  'multiple single quotes' => [
113  "''multiple''",
114  '"\'\'multiple\'\'"',
115  ],
116  'backticks' => [
117  '`backticks`',
118  '"`backticks`"',
119  ],
120  'slashes' => [
121  '/slashes/',
122  '"/slashes/"',
123  ],
124  'backslashes' => [
125  '\\backslashes\\',
126  '"\\backslashes\\"',
127  ],
128  ];
129  }
130 
135  public function ‪quoteIdentifier(string $input, string $expected): void
136  {
137  self::assertSame($expected, $this->connection->quoteIdentifier($input));
138  }
139 
143  public function ‪quoteIdentifiers(): void
144  {
145  $input = [
146  'aField',
147  'anotherField',
148  ];
149 
150  $expected = [
151  '"aField"',
152  '"anotherField"',
153  ];
154 
155  self::assertSame($expected, $this->connection->quoteIdentifiers($input));
156  }
157 
158  public static function ‪insertQueriesDataProvider(): array
159  {
160  return [
161  'single value' => [
162  ['aTestTable', ['aField' => 'aValue']],
163  'INSERT INTO "aTestTable" ("aField") VALUES (?)',
164  ['aValue'],
165  [],
166  ],
167  'multiple values' => [
168  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
169  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
170  ['aValue', 'bValue'],
171  [],
172  ],
173  'with types' => [
174  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], [‪Connection::PARAM_STR, ‪Connection::PARAM_STR]],
175  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
176  ['aValue', 'bValue'],
178  ],
179  'with types for field' => [
180  [
181  'aTestTable',
182  ['aField' => 123, 'bField' => 'bValue'],
183  ['aField' => ‪Connection::PARAM_INT, 'bField' => ‪Connection::PARAM_LOB],
184  ],
185  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
186  [123, 'bValue'],
188  ],
189  ];
190  }
191 
196  public function ‪insertQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes): void
197  {
198  $this->connection->expects(self::once())
199  ->method('executeStatement')
200  ->with($expectedQuery, $expectedValues, $expectedTypes)
201  ->willReturn(1);
202 
203  $this->connection->insert(...‪$args);
204  }
205 
209  public function ‪bulkInsert(): void
210  {
211  $this->connection->expects(self::once())
212  ->method('executeStatement')
213  ->with('INSERT INTO "aTestTable" ("aField") VALUES (?), (?)', ['aValue', 'anotherValue'])
214  ->willReturn(2);
215 
216  $this->connection->bulkInsert('aTestTable', [['aField' => 'aValue'], ['aField' => 'anotherValue']], ['aField']);
217  }
218 
219  public static function ‪updateQueriesDataProvider(): array
220  {
221  return [
222  'single value' => [
223  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1]],
224  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
225  ['aValue', 1],
226  [],
227  ],
228  'multiple values' => [
229  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], ['uid' => 1]],
230  'UPDATE "aTestTable" SET "aField" = ?, "bField" = ? WHERE "uid" = ?',
231  ['aValue', 'bValue', 1],
232  [],
233  ],
234  'with types' => [
235  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], [‪Connection::PARAM_STR]],
236  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
237  ['aValue', 1],
239  ],
240  'with types for field' => [
241  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], ['aField' => ‪Connection::PARAM_LOB]],
242  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
243  ['aValue', 1],
245  ],
246  ];
247  }
248 
253  public function ‪updateQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes): void
254  {
255  // @todo drop else branch and condition once doctrine/dbal is requried in version 2.11.0 minimum
256  if (method_exists(Connection::class, 'executeStatement')) {
257  $this->connection->expects(self::once())
258  ->method('executeStatement')
259  ->with($expectedQuery, $expectedValues, $expectedTypes)
260  ->willReturn(1);
261  } else {
262  $this->connection->expects(self::once())
263  ->method('executeUpdate')
264  ->with($expectedQuery, $expectedValues, $expectedTypes)
265  ->willReturn(1);
266  }
267 
268  $this->connection->update(...‪$args);
269  }
270 
271  public static function ‪deleteQueriesDataProvider(): array
272  {
273  return [
274  'single condition' => [
275  ['aTestTable', ['aField' => 'aValue']],
276  'DELETE FROM "aTestTable" WHERE "aField" = ?',
277  ['aValue'],
278  [],
279  ],
280  'multiple conditions' => [
281  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
282  'DELETE FROM "aTestTable" WHERE "aField" = ? AND "bField" = ?',
283  ['aValue', 'bValue'],
284  [],
285  ],
286  'with types' => [
287  ['aTestTable', ['aField' => 'aValue'], [‪Connection::PARAM_STR]],
288  'DELETE FROM "aTestTable" WHERE "aField" = ?',
289  ['aValue'],
291  ],
292  'with types for field' => [
293  ['aTestTable', ['aField' => 'aValue'], ['aField' => ‪Connection::PARAM_STR]],
294  'DELETE FROM "aTestTable" WHERE "aField" = ?',
295  ['aValue'],
297  ],
298  ];
299  }
300 
305  public function ‪deleteQueries(array ‪$args, string $expectedQuery, array $expectedValues, array $expectedTypes): void
306  {
307  // @todo drop else branch and condition once doctrine/dbal is requried in version 2.11.0 minimum
308  if (method_exists(Connection::class, 'executeStatement')) {
309  $this->connection->expects(self::once())
310  ->method('executeStatement')
311  ->with($expectedQuery, $expectedValues, $expectedTypes)
312  ->willReturn(1);
313  } else {
314  $this->connection->expects(self::once())
315  ->method('executeUpdate')
316  ->with($expectedQuery, $expectedValues, $expectedTypes)
317  ->willReturn(1);
318  }
319 
320  $this->connection->delete(...‪$args);
321  }
322 
331  public static function ‪selectQueriesDataProvider(): array
332  {
333  return [
334  'all columns' => [
335  [['*'], 'aTable'],
336  'SELECT * FROM "aTable"',
337  [],
338  ],
339  'subset of columns' => [
340  [['aField', 'anotherField'], 'aTable'],
341  'SELECT "aField", "anotherField" FROM "aTable"',
342  [],
343  ],
344  'conditions' => [
345  [['*'], 'aTable', ['aField' => 'aValue']],
346  'SELECT * FROM "aTable" WHERE "aField" = :dcValue1',
347  ['dcValue1' => 'aValue'],
348  ],
349  'grouping' => [
350  [['*'], 'aTable', [], ['aField']],
351  'SELECT * FROM "aTable" GROUP BY "aField"',
352  [],
353  ],
354  'ordering' => [
355  [['*'], 'aTable', [], [], ['aField' => 'ASC']],
356  'SELECT * FROM "aTable" ORDER BY "aField" ASC',
357  [],
358  ],
359  'limit' => [
360  [['*'], 'aTable', [], [], [], 1],
361  'SELECT * FROM "aTable" LIMIT 1',
362  [],
363  ],
364  'offset' => [
365  [['*'], 'aTable', [], [], [], 1, 10],
366  'SELECT * FROM "aTable" LIMIT 1 OFFSET 10',
367  [],
368  ],
369  'everything' => [
370  [
371  ['aField', 'anotherField'],
372  'aTable',
373  ['aField' => 'aValue'],
374  ['anotherField'],
375  ['aField' => 'ASC'],
376  1,
377  10,
378  ],
379  'SELECT "aField", "anotherField" FROM "aTable" WHERE "aField" = :dcValue1 ' .
380  'GROUP BY "anotherField" ORDER BY "aField" ASC LIMIT 1 OFFSET 10',
381  ['dcValue1' => 'aValue'],
382  ],
383  ];
384  }
385 
390  public function ‪selectQueries(array ‪$args, string $expectedQuery, array $expectedParameters): void
391  {
392  $resultStatement = $this->createMock(Result::class);
393 
394  $this->connection->expects(self::once())
395  ->method('executeQuery')
396  ->with($expectedQuery, $expectedParameters)
397  ->willReturn($resultStatement);
398 
399  $this->connection->select(...‪$args);
400  }
401 
410  public static function ‪countQueriesDataProvider(): array
411  {
412  return [
413  'all columns' => [
414  ['*', 'aTable', []],
415  'SELECT COUNT(*) FROM "aTable"',
416  [],
417  ],
418  'specified columns' => [
419  ['aField', 'aTable', []],
420  'SELECT COUNT("aField") FROM "aTable"',
421  [],
422  ],
423  'conditions' => [
424  ['aTable.aField', 'aTable', ['aField' => 'aValue']],
425  'SELECT COUNT("aTable"."aField") FROM "aTable" WHERE "aField" = :dcValue1',
426  ['dcValue1' => 'aValue'],
427  ],
428  ];
429  }
430 
435  public function ‪countQueries(array ‪$args, string $expectedQuery, array $expectedParameters): void
436  {
437  $resultStatement = $this->createMock(Result::class);
438 
439  $resultStatement->expects(self::once())
440  ->method('fetchOne')
441  ->willReturn(false);
442  $this->connection->expects(self::once())
443  ->method('executeQuery')
444  ->with($expectedQuery, $expectedParameters)
445  ->willReturn($resultStatement);
446  $this->connection->count(...‪$args);
447  }
448 
452  public function ‪truncateQuery(): void
453  {
454  $this->connection->expects(self::once())
455  ->method('executeStatement')
456  ->with('TRUNCATE "aTestTable"')
457  ->willReturn(0);
458 
459  $this->connection->truncate('aTestTable', false);
460  }
461 
466  {
467  $wrappedConnectionMock = $this->createMock(Connection::class);
468  $wrappedConnectionMock->method('getServerVersion')->willReturn('5.7.11');
469 
470  $this->connection
471  ->method('getWrappedConnection')
472  ->willReturn($wrappedConnectionMock);
473 
474  self::assertSame('5.7.11', $this->connection->getServerVersion());
475  }
476 
481  {
482  $wrappedConnectionMock = $this->createMock(Connection::class);
483  $wrappedConnectionMock->method('getServerVersion')->willReturn('5.7.11');
484 
485  $this->connection
486  ->method('getWrappedConnection')
487  ->willReturn($wrappedConnectionMock);
488 
489  self::assertSame('Mock 5.7.11', $this->connection->getPlatformServerVersion());
490  }
491 }
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\updateQueries
‪updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:253
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\setUp
‪setUp()
Definition: ConnectionTest.php:43
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\getPlatformServerVersionReportsPlatformVersion
‪getPlatformServerVersionReportsPlatformVersion()
Definition: ConnectionTest.php:480
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifierDataProvider
‪static quoteIdentifierDataProvider()
Definition: ConnectionTest.php:84
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\createQueryBuilderReturnsInstanceOfTypo3QueryBuilder
‪createQueryBuilderReturnsInstanceOfTypo3QueryBuilder()
Definition: ConnectionTest.php:79
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:55
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\insertQueries
‪insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:196
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\countQueries
‪countQueries(array $args, string $expectedQuery, array $expectedParameters)
Definition: ConnectionTest.php:435
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\getServerVersionReportsServerVersionOnly
‪getServerVersionReportsServerVersionOnly()
Definition: ConnectionTest.php:465
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifier
‪quoteIdentifier(string $input, string $expected)
Definition: ConnectionTest.php:135
‪TYPO3\CMS\Core\Tests\Unit\Database
Definition: ConnectionPoolTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$connection
‪Connection &MockObject $connection
Definition: ConnectionTest.php:35
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\deleteQueries
‪deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
Definition: ConnectionTest.php:305
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest
Definition: ConnectionTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\selectQueries
‪selectQueries(array $args, string $expectedQuery, array $expectedParameters)
Definition: ConnectionTest.php:390
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\deleteQueriesDataProvider
‪static deleteQueriesDataProvider()
Definition: ConnectionTest.php:271
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\countQueriesDataProvider
‪static countQueriesDataProvider()
Definition: ConnectionTest.php:410
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\bulkInsert
‪bulkInsert()
Definition: ConnectionTest.php:209
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\truncateQuery
‪truncateQuery()
Definition: ConnectionTest.php:452
‪$args
‪$args
Definition: validateRstFiles.php:258
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$testTable
‪string $testTable
Definition: ConnectionTest.php:38
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\quoteIdentifiers
‪quoteIdentifiers()
Definition: ConnectionTest.php:143
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\updateQueriesDataProvider
‪static updateQueriesDataProvider()
Definition: ConnectionTest.php:219
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\selectQueriesDataProvider
‪static selectQueriesDataProvider()
Definition: ConnectionTest.php:331
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\insertQueriesDataProvider
‪static insertQueriesDataProvider()
Definition: ConnectionTest.php:158
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform\MockPlatform
Definition: MockPlatform.php:25
‪TYPO3\CMS\Core\Tests\Unit\Database\ConnectionTest\$platform
‪AbstractPlatform $platform
Definition: ConnectionTest.php:37
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:60