Failed Conditions
Push — master ( 01c22b...e42c1f )
by Marco
79:13 queued 10s
created

ConnectionTest   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 837
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 41
eloc 413
c 2
b 0
f 0
dl 0
loc 837
rs 9.1199

41 Methods

Rating   Name   Duplication   Size   Complexity  
A testIsAutoCommit() 0 3 1
A testSwitchingAutoCommitModeCommitsAllCurrentTransactions() 0 22 1
A testUpdateWithDifferentColumnsInDataAndIdentifiers() 0 37 1
A testFetchColumn() 0 35 1
A testRollBackStartsTransactionInNoAutoCommitMode() 0 15 1
A testFetchArray() 0 34 1
A testDeleteWithIsNull() 0 21 1
A testFetchAssoc() 0 34 1
A testFetchAll() 0 33 1
A testUpdateWithIsNull() 0 35 1
A testUpdateWithSameColumnInDataAndIdentifiers() 0 36 1
A testEmptyInsert() 0 9 1
A testNoTransactionActiveByDefault() 0 3 1
A testCommitWithNoActiveTransactionThrowsException() 0 4 1
A getExecuteUpdateMockConnection() 0 16 1
A testSetRollbackOnlyNoActiveTransactionThrowsException() 0 4 1
A testIsConnected() 0 3 1
A testRollbackWithNoActiveTransactionThrowsException() 0 4 1
A testIsRollbackOnlyNoActiveTransactionThrowsException() 0 4 1
A setUp() 0 3 1
A testGetConfiguration() 0 5 1
A testEventManagerPassedToPlatform() 0 18 1
A testDebugSQLStack() 0 5 1
A testConnectStartsTransactionInNoAutoCommitMode() 0 17 1
A getQueryMethods() 0 8 1
A testEchoSQLLogger() 0 5 1
A testConnectDispatchEvent() 0 16 1
A testDriverExceptionIsWrapped() 0 11 1
A testGetEventManager() 0 3 1
A testGetDriver() 0 3 1
A testSetAutoCommit() 0 4 1
A testCommitStartsTransactionInNoAutoCommitMode() 0 15 1
A testShouldNotPassPlatformInParamsToTheQueryCacheProfileInExecuteCacheQuery() 0 34 1
A testExecuteCacheQueryStripsPlatformFromConnectionParamsBeforeGeneratingCacheKeys() 0 46 1
A testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() 0 8 1
A resultProvider() 0 3 1
A testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCacheQuery() 0 35 1
A testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() 0 31 1
A testCallConnectOnce() 0 12 1
A testThrowsExceptionWhenInValidPlatformSpecified() 0 11 1
A testRethrowsOriginalExceptionOnDeterminingPlatformWhenConnectingToNonExistentDatabase() 0 20 1

How to fix   Complexity   

Complex Class

Complex classes like ConnectionTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ConnectionTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\DBAL;
6
7
use Doctrine\Common\Cache\Cache;
8
use Doctrine\Common\EventManager;
9
use Doctrine\DBAL\Cache\ArrayStatement;
10
use Doctrine\DBAL\Cache\QueryCacheProfile;
11
use Doctrine\DBAL\Configuration;
12
use Doctrine\DBAL\Connection;
13
use Doctrine\DBAL\ConnectionException;
14
use Doctrine\DBAL\DBALException;
15
use Doctrine\DBAL\Driver;
16
use Doctrine\DBAL\Driver\Connection as DriverConnection;
17
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
18
use Doctrine\DBAL\Driver\Statement;
19
use Doctrine\DBAL\DriverManager;
20
use Doctrine\DBAL\Events;
21
use Doctrine\DBAL\Exception\InvalidArgumentException;
22
use Doctrine\DBAL\FetchMode;
23
use Doctrine\DBAL\Logging\DebugStack;
24
use Doctrine\DBAL\Logging\EchoSQLLogger;
25
use Doctrine\DBAL\ParameterType;
26
use Doctrine\DBAL\Platforms\AbstractPlatform;
27
use Doctrine\DBAL\VersionAwarePlatformDriver;
28
use Doctrine\Tests\DbalTestCase;
29
use Exception;
30
use PHPUnit\Framework\MockObject\MockObject;
31
use stdClass;
32
33
/**
34
 * @requires extension pdo_mysql
35
 */
36
class ConnectionTest extends DbalTestCase
37
{
38
    /** @var Connection */
39
    private $connection;
40
41
    /** @var array<string, mixed> */
42
    protected $params = [
43
        'driver' => 'pdo_mysql',
44
        'host' => 'localhost',
45
        'user' => 'root',
46
        'password' => 'password',
47
        'port' => 1234,
48
    ];
49
50
    protected function setUp() : void
51
    {
52
        $this->connection = DriverManager::getConnection($this->params);
53
    }
54
55
    /**
56
     * @return Connection|MockObject
57
     */
58
    private function getExecuteUpdateMockConnection()
59
    {
60
        $driverMock = $this->createMock(Driver::class);
61
62
        $driverMock->expects($this->any())
63
            ->method('connect')
64
            ->will($this->returnValue(
65
                $this->createMock(DriverConnection::class)
66
            ));
67
68
        $platform = $this->getMockForAbstractClass(AbstractPlatform::class);
69
70
        return $this->getMockBuilder(Connection::class)
71
            ->onlyMethods(['executeUpdate'])
72
            ->setConstructorArgs([['platform' => $platform], $driverMock])
73
            ->getMock();
74
    }
75
76
    public function testIsConnected() : void
77
    {
78
        self::assertFalse($this->connection->isConnected());
79
    }
80
81
    public function testNoTransactionActiveByDefault() : void
82
    {
83
        self::assertFalse($this->connection->isTransactionActive());
84
    }
85
86
    public function testCommitWithNoActiveTransactionThrowsException() : void
87
    {
88
        $this->expectException(ConnectionException::class);
89
        $this->connection->commit();
90
    }
91
92
    public function testRollbackWithNoActiveTransactionThrowsException() : void
93
    {
94
        $this->expectException(ConnectionException::class);
95
        $this->connection->rollBack();
96
    }
97
98
    public function testSetRollbackOnlyNoActiveTransactionThrowsException() : void
99
    {
100
        $this->expectException(ConnectionException::class);
101
        $this->connection->setRollbackOnly();
102
    }
103
104
    public function testIsRollbackOnlyNoActiveTransactionThrowsException() : void
105
    {
106
        $this->expectException(ConnectionException::class);
107
        $this->connection->isRollbackOnly();
108
    }
109
110
    public function testGetConfiguration() : void
111
    {
112
        $config = $this->connection->getConfiguration();
113
114
        self::assertInstanceOf(Configuration::class, $config);
115
    }
116
117
    public function testGetDriver() : void
118
    {
119
        self::assertInstanceOf(\Doctrine\DBAL\Driver\PDOMySql\Driver::class, $this->connection->getDriver());
120
    }
121
122
    public function testGetEventManager() : void
123
    {
124
        self::assertInstanceOf(EventManager::class, $this->connection->getEventManager());
125
    }
126
127
    public function testConnectDispatchEvent() : void
128
    {
129
        $listenerMock = $this->getMockBuilder($this->getMockClass('ConnectDispatchEventListener'))
130
            ->addMethods(['postConnect'])
131
            ->getMock();
132
        $listenerMock->expects($this->once())->method('postConnect');
133
134
        $eventManager = new EventManager();
135
        $eventManager->addEventListener([Events::postConnect], $listenerMock);
136
137
        $driverMock = $this->createMock(Driver::class);
138
        $driverMock->expects($this->at(0))
139
                   ->method('connect');
140
141
        $conn = new Connection([], $driverMock, new Configuration(), $eventManager);
142
        $conn->connect();
143
    }
144
145
    public function testEventManagerPassedToPlatform() : void
146
    {
147
        $eventManager = new EventManager();
148
149
        /** @var AbstractPlatform|MockObject $driver */
150
        $platform = $this->createMock(AbstractPlatform::class);
151
        $platform->expects($this->once())
152
            ->method('setEventManager')
153
            ->with($eventManager);
154
155
        /** @var Driver|MockObject $driver */
156
        $driver = $this->createMock(Driver::class);
157
        $driver->expects($this->any())
158
            ->method('getDatabasePlatform')
159
            ->willReturn($platform);
160
161
        $connection = new Connection($this->params, $driver, null, $eventManager);
162
        $connection->getDatabasePlatform();
163
    }
164
165
    /**
166
     * @requires extension pdo_sqlite
167
     * @dataProvider getQueryMethods
168
     */
169
    public function testDriverExceptionIsWrapped(string $method) : void
170
    {
171
        $this->expectException(DBALException::class);
172
        $this->expectExceptionMessage("An exception occurred while executing \"MUUHAAAAHAAAA\":\n\nSQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\"");
173
174
        $connection = DriverManager::getConnection([
175
            'driver' => 'pdo_sqlite',
176
            'memory' => true,
177
        ]);
178
179
        $connection->$method('MUUHAAAAHAAAA');
180
    }
181
182
    /**
183
     * @return array<int, array<int, mixed>>
184
     */
185
    public static function getQueryMethods() : iterable
186
    {
187
        return [
188
            ['exec'],
189
            ['query'],
190
            ['executeQuery'],
191
            ['executeUpdate'],
192
            ['prepare'],
193
        ];
194
    }
195
196
    /**
197
     * Pretty dumb test, however we want to check that the EchoSQLLogger correctly implements the interface.
198
     *
199
     * @group DBAL-11
200
     */
201
    public function testEchoSQLLogger() : void
202
    {
203
        $logger = new EchoSQLLogger();
204
        $this->connection->getConfiguration()->setSQLLogger($logger);
205
        self::assertSame($logger, $this->connection->getConfiguration()->getSQLLogger());
206
    }
207
208
    /**
209
     * Pretty dumb test, however we want to check that the DebugStack correctly implements the interface.
210
     *
211
     * @group DBAL-11
212
     */
213
    public function testDebugSQLStack() : void
214
    {
215
        $logger = new DebugStack();
216
        $this->connection->getConfiguration()->setSQLLogger($logger);
217
        self::assertSame($logger, $this->connection->getConfiguration()->getSQLLogger());
218
    }
219
220
    /**
221
     * @group DBAL-81
222
     */
223
    public function testIsAutoCommit() : void
224
    {
225
        self::assertTrue($this->connection->isAutoCommit());
226
    }
227
228
    /**
229
     * @group DBAL-81
230
     */
231
    public function testSetAutoCommit() : void
232
    {
233
        $this->connection->setAutoCommit(false);
234
        self::assertFalse($this->connection->isAutoCommit());
235
    }
236
237
    /**
238
     * @group DBAL-81
239
     */
240
    public function testConnectStartsTransactionInNoAutoCommitMode() : void
241
    {
242
        $driverMock = $this->createMock(Driver::class);
243
        $driverMock->expects($this->any())
244
            ->method('connect')
245
            ->will($this->returnValue(
246
                $this->createMock(DriverConnection::class)
247
            ));
248
        $conn = new Connection([], $driverMock);
249
250
        $conn->setAutoCommit(false);
251
252
        self::assertFalse($conn->isTransactionActive());
253
254
        $conn->connect();
255
256
        self::assertTrue($conn->isTransactionActive());
257
    }
258
259
    /**
260
     * @group DBAL-81
261
     */
262
    public function testCommitStartsTransactionInNoAutoCommitMode() : void
263
    {
264
        $driverMock = $this->createMock(Driver::class);
265
        $driverMock->expects($this->any())
266
            ->method('connect')
267
            ->will($this->returnValue(
268
                $this->createMock(DriverConnection::class)
269
            ));
270
        $conn = new Connection([], $driverMock);
271
272
        $conn->setAutoCommit(false);
273
        $conn->connect();
274
        $conn->commit();
275
276
        self::assertTrue($conn->isTransactionActive());
277
    }
278
279
    /**
280
     * @return bool[][]
281
     */
282
    public function resultProvider() : array
283
    {
284
        return [[true], [false]];
285
    }
286
287
    /**
288
     * @group DBAL-81
289
     */
290
    public function testRollBackStartsTransactionInNoAutoCommitMode() : void
291
    {
292
        $driverMock = $this->createMock(Driver::class);
293
        $driverMock->expects($this->any())
294
            ->method('connect')
295
            ->will($this->returnValue(
296
                $this->createMock(DriverConnection::class)
297
            ));
298
        $conn = new Connection([], $driverMock);
299
300
        $conn->setAutoCommit(false);
301
        $conn->connect();
302
        $conn->rollBack();
303
304
        self::assertTrue($conn->isTransactionActive());
305
    }
306
307
    /**
308
     * @group DBAL-81
309
     */
310
    public function testSwitchingAutoCommitModeCommitsAllCurrentTransactions() : void
311
    {
312
        $driverMock = $this->createMock(Driver::class);
313
        $driverMock->expects($this->any())
314
            ->method('connect')
315
            ->will($this->returnValue(
316
                $this->createMock(DriverConnection::class)
317
            ));
318
        $conn = new Connection([], $driverMock);
319
320
        $conn->connect();
321
        $conn->beginTransaction();
322
        $conn->beginTransaction();
323
        $conn->setAutoCommit(false);
324
325
        self::assertSame(1, $conn->getTransactionNestingLevel());
326
327
        $conn->beginTransaction();
328
        $conn->beginTransaction();
329
        $conn->setAutoCommit(true);
330
331
        self::assertFalse($conn->isTransactionActive());
332
    }
333
334
    public function testEmptyInsert() : void
335
    {
336
        $conn = $this->getExecuteUpdateMockConnection();
337
338
        $conn->expects($this->once())
339
            ->method('executeUpdate')
340
            ->with('INSERT INTO footable () VALUES ()');
341
342
        $conn->insert('footable', []);
343
    }
344
345
    /**
346
     * @group DBAL-2511
347
     */
348
    public function testUpdateWithDifferentColumnsInDataAndIdentifiers() : void
349
    {
350
        $conn = $this->getExecuteUpdateMockConnection();
351
352
        $conn->expects($this->once())
353
            ->method('executeUpdate')
354
            ->with(
355
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id = ? AND name = ?',
356
                [
357
                    'some text',
358
                    true,
359
                    1,
360
                    'foo',
361
                ],
362
                [
363
                    'string',
364
                    'boolean',
365
                    'integer',
366
                    'string',
367
                ]
368
            );
369
370
        $conn->update(
371
            'TestTable',
372
            [
373
                'text' => 'some text',
374
                'is_edited' => true,
375
            ],
376
            [
377
                'id' => 1,
378
                'name' => 'foo',
379
            ],
380
            [
381
                'text' => 'string',
382
                'is_edited' => 'boolean',
383
                'id' => 'integer',
384
                'name' => 'string',
385
            ]
386
        );
387
    }
388
389
    /**
390
     * @group DBAL-2511
391
     */
392
    public function testUpdateWithSameColumnInDataAndIdentifiers() : void
393
    {
394
        $conn = $this->getExecuteUpdateMockConnection();
395
396
        $conn->expects($this->once())
397
            ->method('executeUpdate')
398
            ->with(
399
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id = ? AND is_edited = ?',
400
                [
401
                    'some text',
402
                    true,
403
                    1,
404
                    false,
405
                ],
406
                [
407
                    'string',
408
                    'boolean',
409
                    'integer',
410
                    'boolean',
411
                ]
412
            );
413
414
        $conn->update(
415
            'TestTable',
416
            [
417
                'text' => 'some text',
418
                'is_edited' => true,
419
            ],
420
            [
421
                'id' => 1,
422
                'is_edited' => false,
423
            ],
424
            [
425
                'text' => 'string',
426
                'is_edited' => 'boolean',
427
                'id' => 'integer',
428
            ]
429
        );
430
    }
431
432
    /**
433
     * @group DBAL-2688
434
     */
435
    public function testUpdateWithIsNull() : void
436
    {
437
        $conn = $this->getExecuteUpdateMockConnection();
438
439
        $conn->expects($this->once())
440
            ->method('executeUpdate')
441
            ->with(
442
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id IS NULL AND name = ?',
443
                [
444
                    'some text',
445
                    null,
446
                    'foo',
447
                ],
448
                [
449
                    'string',
450
                    'boolean',
451
                    'string',
452
                ]
453
            );
454
455
        $conn->update(
456
            'TestTable',
457
            [
458
                'text' => 'some text',
459
                'is_edited' => null,
460
            ],
461
            [
462
                'id' => null,
463
                'name' => 'foo',
464
            ],
465
            [
466
                'text' => 'string',
467
                'is_edited' => 'boolean',
468
                'id' => 'integer',
469
                'name' => 'string',
470
            ]
471
        );
472
    }
473
474
    /**
475
     * @group DBAL-2688
476
     */
477
    public function testDeleteWithIsNull() : void
478
    {
479
        $conn = $this->getExecuteUpdateMockConnection();
480
481
        $conn->expects($this->once())
482
            ->method('executeUpdate')
483
            ->with(
484
                'DELETE FROM TestTable WHERE id IS NULL AND name = ?',
485
                ['foo'],
486
                ['string']
487
            );
488
489
        $conn->delete(
490
            'TestTable',
491
            [
492
                'id' => null,
493
                'name' => 'foo',
494
            ],
495
            [
496
                'id' => 'integer',
497
                'name' => 'string',
498
            ]
499
        );
500
    }
501
502
    public function testFetchAssoc() : void
503
    {
504
        $statement = 'SELECT * FROM foo WHERE bar = ?';
505
        $params    = [666];
506
        $types     = [ParameterType::INTEGER];
507
        $result    = [];
508
509
        $driverMock = $this->createMock(Driver::class);
510
511
        $driverMock->expects($this->any())
512
            ->method('connect')
513
            ->will($this->returnValue(
514
                $this->createMock(DriverConnection::class)
515
            ));
516
517
        $driverStatementMock = $this->createMock(Statement::class);
518
519
        $driverStatementMock->expects($this->once())
520
            ->method('fetch')
521
            ->with(FetchMode::ASSOCIATIVE)
522
            ->will($this->returnValue($result));
523
524
        /** @var Connection|MockObject $conn */
525
        $conn = $this->getMockBuilder(Connection::class)
526
            ->onlyMethods(['executeQuery'])
527
            ->setConstructorArgs([[], $driverMock])
528
            ->getMock();
529
530
        $conn->expects($this->once())
531
            ->method('executeQuery')
532
            ->with($statement, $params, $types)
533
            ->will($this->returnValue($driverStatementMock));
534
535
        self::assertSame($result, $conn->fetchAssoc($statement, $params, $types));
536
    }
537
538
    public function testFetchArray() : void
539
    {
540
        $statement = 'SELECT * FROM foo WHERE bar = ?';
541
        $params    = [666];
542
        $types     = [ParameterType::INTEGER];
543
        $result    = [];
544
545
        $driverMock = $this->createMock(Driver::class);
546
547
        $driverMock->expects($this->any())
548
            ->method('connect')
549
            ->will($this->returnValue(
550
                $this->createMock(DriverConnection::class)
551
            ));
552
553
        $driverStatementMock = $this->createMock(Statement::class);
554
555
        $driverStatementMock->expects($this->once())
556
            ->method('fetch')
557
            ->with(FetchMode::NUMERIC)
558
            ->will($this->returnValue($result));
559
560
        /** @var Connection|MockObject $conn */
561
        $conn = $this->getMockBuilder(Connection::class)
562
            ->onlyMethods(['executeQuery'])
563
            ->setConstructorArgs([[], $driverMock])
564
            ->getMock();
565
566
        $conn->expects($this->once())
567
            ->method('executeQuery')
568
            ->with($statement, $params, $types)
569
            ->will($this->returnValue($driverStatementMock));
570
571
        self::assertSame($result, $conn->fetchArray($statement, $params, $types));
572
    }
573
574
    public function testFetchColumn() : void
575
    {
576
        $statement = 'SELECT * FROM foo WHERE bar = ?';
577
        $params    = [666];
578
        $types     = [ParameterType::INTEGER];
579
        $column    = 0;
580
        $result    = [];
581
582
        $driverMock = $this->createMock(Driver::class);
583
584
        $driverMock->expects($this->any())
585
            ->method('connect')
586
            ->will($this->returnValue(
587
                $this->createMock(DriverConnection::class)
588
            ));
589
590
        $driverStatementMock = $this->createMock(Statement::class);
591
592
        $driverStatementMock->expects($this->once())
593
            ->method('fetchColumn')
594
            ->with($column)
595
            ->will($this->returnValue($result));
596
597
        /** @var Connection|MockObject $conn */
598
        $conn = $this->getMockBuilder(Connection::class)
599
            ->onlyMethods(['executeQuery'])
600
            ->setConstructorArgs([[], $driverMock])
601
            ->getMock();
602
603
        $conn->expects($this->once())
604
            ->method('executeQuery')
605
            ->with($statement, $params, $types)
606
            ->will($this->returnValue($driverStatementMock));
607
608
        self::assertSame($result, $conn->fetchColumn($statement, $params, $column, $types));
609
    }
610
611
    public function testFetchAll() : void
612
    {
613
        $statement = 'SELECT * FROM foo WHERE bar = ?';
614
        $params    = [666];
615
        $types     = [ParameterType::INTEGER];
616
        $result    = [];
617
618
        $driverMock = $this->createMock(Driver::class);
619
620
        $driverMock->expects($this->any())
621
            ->method('connect')
622
            ->will($this->returnValue(
623
                $this->createMock(DriverConnection::class)
624
            ));
625
626
        $driverStatementMock = $this->createMock(Statement::class);
627
628
        $driverStatementMock->expects($this->once())
629
            ->method('fetchAll')
630
            ->will($this->returnValue($result));
631
632
        /** @var Connection|MockObject $conn */
633
        $conn = $this->getMockBuilder(Connection::class)
634
            ->onlyMethods(['executeQuery'])
635
            ->setConstructorArgs([[], $driverMock])
636
            ->getMock();
637
638
        $conn->expects($this->once())
639
            ->method('executeQuery')
640
            ->with($statement, $params, $types)
641
            ->will($this->returnValue($driverStatementMock));
642
643
        self::assertSame($result, $conn->fetchAll($statement, $params, $types));
644
    }
645
646
    public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void
647
    {
648
        /** @var Driver $driver */
649
        $driver = $this->createMock(Driver::class);
650
        $conn   = new Connection([], $driver);
651
652
        $this->expectException(InvalidArgumentException::class);
653
        $conn->delete('kittens', []);
654
    }
655
656
    public function testCallConnectOnce() : void
657
    {
658
        /** @var Driver|MockObject $driver */
659
        $driver = $this->createMock(Driver::class);
660
        $driver->expects($this->once())
661
            ->method('connect');
662
663
        $platform = $this->createMock(AbstractPlatform::class);
664
665
        $conn = new Connection(['platform' => $platform], $driver);
666
        $conn->connect();
667
        $conn->connect();
668
    }
669
670
    /**
671
     * @group DBAL-1127
672
     */
673
    public function testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() : void
674
    {
675
        /** @var Driver|VersionAwarePlatformDriver|MockObject $driverMock */
676
        $driverMock = $this->createMock([Driver::class, VersionAwarePlatformDriver::class]);
677
678
        /** @var DriverConnection|ServerInfoAwareConnection|MockObject $driverConnectionMock */
679
        $driverConnectionMock = $this->createMock([DriverConnection::class, ServerInfoAwareConnection::class]);
680
681
        /** @var AbstractPlatform|MockObject $platformMock */
682
        $platformMock = $this->getMockForAbstractClass(AbstractPlatform::class);
683
684
        $connection = new Connection([], $driverMock);
685
686
        $driverMock->expects($this->once())
687
            ->method('connect')
688
            ->will($this->returnValue($driverConnectionMock));
689
690
        $driverConnectionMock->expects($this->once())
691
            ->method('requiresQueryForServerVersion')
692
            ->will($this->returnValue(false));
693
694
        $driverConnectionMock->expects($this->once())
695
            ->method('getServerVersion')
696
            ->will($this->returnValue('6.6.6'));
697
698
        $driverMock->expects($this->once())
699
            ->method('createDatabasePlatformForVersion')
700
            ->with('6.6.6')
701
            ->will($this->returnValue($platformMock));
702
703
        self::assertSame($platformMock, $connection->getDatabasePlatform());
704
    }
705
706
    public function testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCacheQuery() : void
707
    {
708
        $resultCacheDriverMock = $this->createMock(Cache::class);
709
710
        $resultCacheDriverMock
711
            ->expects($this->atLeastOnce())
712
            ->method('fetch')
713
            ->with('cacheKey')
714
            ->will($this->returnValue(['realKey' => []]));
715
716
        $query  = 'SELECT * FROM foo WHERE bar = ?';
717
        $params = [666];
718
        $types  = [ParameterType::INTEGER];
719
720
        /** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
721
        $queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
722
723
        $queryCacheProfileMock
724
            ->expects($this->any())
725
            ->method('getResultCacheDriver')
726
            ->will($this->returnValue($resultCacheDriverMock));
727
728
        // This is our main expectation
729
        $queryCacheProfileMock
730
            ->expects($this->once())
731
            ->method('generateCacheKeys')
732
            ->with($query, $params, $types, $this->params)
733
            ->will($this->returnValue(['cacheKey', 'realKey']));
734
735
        /** @var Driver $driver */
736
        $driver = $this->createMock(Driver::class);
737
738
        self::assertInstanceOf(
739
            ArrayStatement::class,
740
            (new Connection($this->params, $driver))->executeCacheQuery($query, $params, $types, $queryCacheProfileMock)
741
        );
742
    }
743
744
    /**
745
     * @group #2821
746
     */
747
    public function testShouldNotPassPlatformInParamsToTheQueryCacheProfileInExecuteCacheQuery() : void
748
    {
749
        $resultCacheDriverMock = $this->createMock(Cache::class);
750
751
        $resultCacheDriverMock
752
            ->expects($this->atLeastOnce())
753
            ->method('fetch')
754
            ->with('cacheKey')
755
            ->will($this->returnValue(['realKey' => []]));
756
757
        /** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
758
        $queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
759
760
        $queryCacheProfileMock
761
            ->expects($this->any())
762
            ->method('getResultCacheDriver')
763
            ->will($this->returnValue($resultCacheDriverMock));
764
765
        $query = 'SELECT 1';
766
767
        $connectionParams = $this->params;
768
769
        $queryCacheProfileMock
770
            ->expects($this->once())
771
            ->method('generateCacheKeys')
772
            ->with($query, [], [], $connectionParams)
773
            ->will($this->returnValue(['cacheKey', 'realKey']));
774
775
        $connectionParams['platform'] = $this->createMock(AbstractPlatform::class);
776
777
        /** @var Driver $driver */
778
        $driver = $this->createMock(Driver::class);
779
780
        (new Connection($connectionParams, $driver))->executeCacheQuery($query, [], [], $queryCacheProfileMock);
781
    }
782
783
    /**
784
     * @group #2821
785
     */
786
    public function testThrowsExceptionWhenInValidPlatformSpecified() : void
787
    {
788
        $connectionParams             = $this->params;
789
        $connectionParams['platform'] = new stdClass();
790
791
        /** @var Driver $driver */
792
        $driver = $this->createMock(Driver::class);
793
794
        $this->expectException(DBALException::class);
795
796
        new Connection($connectionParams, $driver);
797
    }
798
799
    /**
800
     * @group DBAL-990
801
     */
802
    public function testRethrowsOriginalExceptionOnDeterminingPlatformWhenConnectingToNonExistentDatabase() : void
803
    {
804
        /** @var Driver|VersionAwarePlatformDriver|MockObject $driverMock */
805
        $driverMock = $this->createMock([Driver::class, VersionAwarePlatformDriver::class]);
806
807
        $connection        = new Connection(['dbname' => 'foo'], $driverMock);
808
        $originalException = new Exception('Original exception');
809
        $fallbackException = new Exception('Fallback exception');
810
811
        $driverMock->expects($this->at(0))
812
            ->method('connect')
813
            ->willThrowException($originalException);
814
815
        $driverMock->expects($this->at(1))
816
            ->method('connect')
817
            ->willThrowException($fallbackException);
818
819
        $this->expectExceptionMessage($originalException->getMessage());
820
821
        $connection->getDatabasePlatform();
822
    }
823
824
    /**
825
     * @group #3194
826
     */
827
    public function testExecuteCacheQueryStripsPlatformFromConnectionParamsBeforeGeneratingCacheKeys() : void
828
    {
829
        /** @var Driver|MockObject $driver */
830
        $driver = $this->createMock(Driver::class);
831
832
        /** @var AbstractPlatform|MockObject $platform */
833
        $platform = $this->createMock(AbstractPlatform::class);
834
835
        /** @var QueryCacheProfile|MockObject $queryCacheProfile */
836
        $queryCacheProfile = $this->createMock(QueryCacheProfile::class);
837
838
        /** @var Cache|MockObject $resultCacheDriver */
839
        $resultCacheDriver = $this->createMock(Cache::class);
840
841
        $queryCacheProfile
842
            ->expects($this->any())
843
            ->method('getResultCacheDriver')
844
            ->will($this->returnValue($resultCacheDriver));
845
846
        $resultCacheDriver
847
            ->expects($this->atLeastOnce())
848
            ->method('fetch')
849
            ->with('cacheKey')
850
            ->will($this->returnValue(['realKey' => []]));
851
852
        $query = 'SELECT 1';
853
854
        $params = [
855
            'dbname' => 'foo',
856
            'platform' => $platform,
857
        ];
858
859
        $paramsWithoutPlatform = $params;
860
        unset($paramsWithoutPlatform['platform']);
861
862
        $queryCacheProfile
863
            ->expects($this->once())
864
            ->method('generateCacheKeys')
865
            ->with($query, [], [], $paramsWithoutPlatform)
866
            ->will($this->returnValue(['cacheKey', 'realKey']));
867
868
        $connection = new Connection($params, $driver);
869
870
        self::assertSame($params, $connection->getParams());
871
872
        $connection->executeCacheQuery($query, [], [], $queryCacheProfile);
873
    }
874
}
875