Completed
Pull Request — master (#3304)
by Šimon
61:54
created

ConnectionTest::testEmptyInsert()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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