Passed
Push — master ( be06f7...c027e3 )
by Wilmer
08:58 queued 06:59
created

TestConnectionTrait::testEnableQueryLog()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 90
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 55
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 54
nc 3
nop 0
dl 0
loc 90
ccs 55
cts 55
cp 1
crap 3
rs 9.0036
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestUtility;
6
7
use Yiisoft\Db\Connection\ConnectionInterface;
8
use Yiisoft\Db\Exception\Exception;
9
use Yiisoft\Db\Exception\NotSupportedException;
10
use Yiisoft\Db\Transaction\Transaction;
11
12
use function serialize;
13
use function unserialize;
14
15
trait TestConnectionTrait
16
{
17 4
    public function testSerialize(): void
18
    {
19 4
        $db = $this->getConnection();
0 ignored issues
show
Bug introduced by
It seems like getConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

19
        /** @scrutinizer ignore-call */ 
20
        $db = $this->getConnection();
Loading history...
20
21 4
        $db->open();
22
23 4
        $serialized = serialize($db);
24
25 4
        $this->assertNotNull($db->getPDO());
0 ignored issues
show
Bug introduced by
It seems like assertNotNull() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

25
        $this->/** @scrutinizer ignore-call */ 
26
               assertNotNull($db->getPDO());
Loading history...
26
27 4
        $unserialized = unserialize($serialized);
28
29 4
        $this->assertInstanceOf(ConnectionInterface::class, $unserialized);
0 ignored issues
show
Bug introduced by
It seems like assertInstanceOf() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

29
        $this->/** @scrutinizer ignore-call */ 
30
               assertInstanceOf(ConnectionInterface::class, $unserialized);
Loading history...
30 4
        $this->assertNull($unserialized->getPDO());
0 ignored issues
show
Bug introduced by
It seems like assertNull() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

30
        $this->/** @scrutinizer ignore-call */ 
31
               assertNull($unserialized->getPDO());
Loading history...
31 4
        $this->assertEquals(123, $unserialized->createCommand('SELECT 123')->queryScalar());
0 ignored issues
show
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

31
        $this->/** @scrutinizer ignore-call */ 
32
               assertEquals(123, $unserialized->createCommand('SELECT 123')->queryScalar());
Loading history...
32 4
    }
33
34 4
    public function testTransaction(): void
35
    {
36 4
        $db = $this->getConnection();
37
38 4
        $this->assertNull($db->getTransaction());
39
40 4
        $transaction = $db->beginTransaction();
41
42 4
        $this->assertNotNull($db->getTransaction());
43 4
        $this->assertTrue($transaction->isActive());
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
        $this->/** @scrutinizer ignore-call */ 
44
               assertTrue($transaction->isActive());
Loading history...
44
45 4
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
46
47 4
        $transaction->rollBack();
48
49 4
        $this->assertFalse($transaction->isActive());
0 ignored issues
show
Bug introduced by
It seems like assertFalse() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

49
        $this->/** @scrutinizer ignore-call */ 
50
               assertFalse($transaction->isActive());
Loading history...
50 4
        $this->assertNull($db->getTransaction());
51 4
        $this->assertEquals(0, $db->createCommand(
52 4
            "SELECT COUNT(*) FROM profile WHERE description = 'test transaction';"
53 4
        )->queryScalar());
54
55 4
        $transaction = $db->beginTransaction();
56
57 4
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
58
59 4
        $transaction->commit();
60
61 4
        $this->assertFalse($transaction->isActive());
62 4
        $this->assertNull($db->getTransaction());
63 4
        $this->assertEquals(1, $db->createCommand(
64 4
            "SELECT COUNT(*) FROM profile WHERE description = 'test transaction';"
65 4
        )->queryScalar());
66 4
    }
67
68 2
    public function testTransactionIsolation(): void
69
    {
70 2
        $db = $this->getConnection(true);
71
72 2
        $transaction = $db->beginTransaction(Transaction::READ_UNCOMMITTED);
73
74 2
        $transaction->commit();
75
76 2
        $transaction = $db->beginTransaction(Transaction::READ_COMMITTED);
77
78 2
        $transaction->commit();
79
80 2
        $transaction = $db->beginTransaction(Transaction::REPEATABLE_READ);
81
82 2
        $transaction->commit();
83
84 2
        $transaction = $db->beginTransaction(Transaction::SERIALIZABLE);
85
86 2
        $transaction->commit();
87
88
        /* should not be any exception so far */
89 2
        $this->assertTrue(true);
90 2
    }
91
92 4
    public function testTransactionShortcutException(): void
93
    {
94 4
        $db = $this->getConnection();
95
96 4
        $result = $db->transaction(static function (ConnectionInterface $db) {
97 4
            $db->createCommand()->insert('profile', ['description' => 'test transaction shortcut'])->execute();
98 4
            return true;
99 4
        }, Transaction::READ_UNCOMMITTED);
100
101 4
        $this->assertTrue($result, 'transaction shortcut valid value should be returned from callback');
102
103 4
        $profilesCount = $db->createCommand(
104 4
            "SELECT COUNT(*) FROM profile WHERE description = 'test transaction shortcut';"
105 4
        )->queryScalar();
106
107 4
        $this->assertEquals(1, $profilesCount, 'profile should be inserted in transaction shortcut');
108 4
    }
109
110 4
    public function testTransactionShortcutCorrect(): void
111
    {
112 4
        $db = $this->getConnection(true);
113
114 4
        $result = $db->transaction(static function () use ($db) {
115 4
            $db->createCommand()->insert('profile', ['description' => 'test transaction shortcut'])->execute();
116 4
            return true;
117 4
        });
118
119 4
        $this->assertTrue($result, 'transaction shortcut valid value should be returned from callback');
120
121 4
        $profilesCount = $db->createCommand(
122 4
            "SELECT COUNT(*) FROM profile WHERE description = 'test transaction shortcut';"
123 4
        )->queryScalar();
124
125 4
        $this->assertEquals(1, $profilesCount, 'profile should be inserted in transaction shortcut');
126 4
    }
127
128 4
    public function testTransactionShortcutCustom(): void
129
    {
130 4
        $db = $this->getConnection(true);
131
132 4
        $result = $db->transaction(static function (ConnectionInterface $db) {
133 4
            $db->createCommand()->insert('profile', ['description' => 'test transaction shortcut'])->execute();
134 4
            return true;
135 4
        }, Transaction::READ_UNCOMMITTED);
136
137 4
        $this->assertTrue($result, 'transaction shortcut valid value should be returned from callback');
138
139 4
        $profilesCount = $db->createCommand(
140 4
            "SELECT COUNT(*) FROM profile WHERE description = 'test transaction shortcut';"
141 4
        )->queryScalar();
142
143 4
        $this->assertEquals(1, $profilesCount, 'profile should be inserted in transaction shortcut');
144 4
    }
145
146
    /**
147
     * Tests nested transactions with partial rollback.
148
     *
149
     * {@see https://github.com/yiisoft/yii2/issues/9851}
150
     */
151 4
    public function testNestedTransaction(): void
152
    {
153 4
        $db = $this->getConnection();
154
155 4
        $db->transaction(function (ConnectionInterface $db) {
156 4
            $this->assertNotNull($db->getTransaction());
0 ignored issues
show
Bug introduced by
The method getTransaction() does not exist on Yiisoft\Db\Connection\ConnectionInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Db\Connection\ConnectionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
            $this->assertNotNull($db->/** @scrutinizer ignore-call */ getTransaction());
Loading history...
157
158 4
            $db->transaction(function (ConnectionInterface $db) {
0 ignored issues
show
Bug introduced by
The method transaction() does not exist on Yiisoft\Db\Connection\ConnectionInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Db\Connection\ConnectionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
            $db->/** @scrutinizer ignore-call */ 
159
                 transaction(function (ConnectionInterface $db) {
Loading history...
159 4
                $this->assertNotNull($db->getTransaction());
160 4
                $db->getTransaction()->rollBack();
161 4
            });
162
163 4
            $this->assertNotNull($db->getTransaction());
164 4
        });
165 4
    }
166
167 4
    public function testNestedTransactionNotSupported(): void
168
    {
169 4
        $db = $this->getConnection();
170
171 4
        $db->setEnableSavepoint(false);
172
173 4
        $db->transaction(function (ConnectionInterface $db) {
174 4
            $this->assertNotNull($db->getTransaction());
175 4
            $this->expectException(NotSupportedException::class);
0 ignored issues
show
Bug introduced by
It seems like expectException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
            $this->/** @scrutinizer ignore-call */ 
176
                   expectException(NotSupportedException::class);
Loading history...
176 4
            $db->beginTransaction();
0 ignored issues
show
Bug introduced by
The method beginTransaction() does not exist on Yiisoft\Db\Connection\ConnectionInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Db\Connection\ConnectionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

176
            $db->/** @scrutinizer ignore-call */ 
177
                 beginTransaction();
Loading history...
177 4
        });
178
    }
179
180 4
    public function testEnableQueryLog(): void
181
    {
182 4
        $db = $this->getConnection();
183
184 4
        foreach (['qlog1', 'qlog2', 'qlog3', 'qlog4'] as $table) {
185 4
            if ($db->getTableSchema($table, true) !== null) {
186 1
                $db->createCommand()->dropTable($table)->execute();
187
            }
188
        }
189
190
        /* profiling and logging */
191 4
        $db->setEnableLogging(true);
192 4
        $db->setEnableProfiling(true);
193
194 4
        $this->logger->flush();
195 4
        $this->profiler->flush();
196
197 4
        $db->createCommand()->createTable('qlog1', ['id' => 'pk'])->execute();
198
199 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->logger, 'messages'));
0 ignored issues
show
Bug introduced by
It seems like getInaccessibleProperty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
        $this->assertCount(1, $this->/** @scrutinizer ignore-call */ getInaccessibleProperty($this->logger, 'messages'));
Loading history...
Bug introduced by
It seems like assertCount() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
        $this->/** @scrutinizer ignore-call */ 
200
               assertCount(1, $this->getInaccessibleProperty($this->logger, 'messages'));
Loading history...
200 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->profiler, 'messages'));
201 4
        $this->assertNotNull($db->getTableSchema('qlog1', true));
202
203 4
        $this->logger->flush();
204 4
        $this->profiler->flush();
205
206 4
        $db->createCommand('SELECT * FROM qlog1')->queryAll();
207
208 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->logger, 'messages'));
209 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->profiler, 'messages'));
210
211
        /* profiling only */
212 4
        $db->setEnableLogging(false);
213 4
        $db->setEnableProfiling(true);
214
215 4
        $this->logger->flush();
216 4
        $this->profiler->flush();
217
218 4
        $db->createCommand()->createTable('qlog2', ['id' => 'pk'])->execute();
219
220 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->logger, 'messages'));
221 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->profiler, 'messages'));
222 4
        $this->assertNotNull($db->getTableSchema('qlog2', true));
223
224 4
        $this->logger->flush();
225 4
        $this->profiler->flush();
226
227 4
        $db->createCommand('SELECT * FROM qlog2')->queryAll();
228
229 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->logger, 'messages'));
230 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->profiler, 'messages'));
231
232
        /* logging only */
233 4
        $db->setEnableLogging(true);
234 4
        $db->setEnableProfiling(false);
235
236 4
        $this->logger->flush();
237 4
        $this->profiler->flush();
238
239 4
        $db->createCommand()->createTable('qlog3', ['id' => 'pk'])->execute();
240
241 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->logger, 'messages'));
242 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->profiler, 'messages'));
243 4
        $this->assertNotNull($db->getTableSchema('qlog3', true));
244
245 4
        $this->logger->flush();
246 4
        $this->profiler->flush();
247
248 4
        $db->createCommand('SELECT * FROM qlog3')->queryAll();
249
250 4
        $this->assertCount(1, $this->getInaccessibleProperty($this->logger, 'messages'));
251 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->profiler, 'messages'));
252
253
        /* disabled */
254 4
        $db->setEnableLogging(false);
255 4
        $db->setEnableProfiling(false);
256
257 4
        $this->logger->flush();
258 4
        $this->profiler->flush();
259
260 4
        $db->createCommand()->createTable('qlog4', ['id' => 'pk'])->execute();
261
262 4
        $this->assertNotNull($db->getTableSchema('qlog4', true));
263 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->logger, 'messages'));
264 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->profiler, 'messages'));
265
266 4
        $db->createCommand('SELECT * FROM qlog4')->queryAll();
267
268 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->logger, 'messages'));
269 4
        $this->assertCount(0, $this->getInaccessibleProperty($this->profiler, 'messages'));
270 4
    }
271
272 3
    public function testExceptionContainsRawQuery(): void
273
    {
274 3
        $db = $this->getConnection();
275
276 3
        if ($db->getTableSchema('qlog1', true) === null) {
277
            $db->createCommand()->createTable('qlog1', ['id' => 'pk'])->execute();
278
        }
279
280 3
        $db->setEmulatePrepare(true);
281
282
        /* profiling and logging */
283 3
        $db->setEnableLogging(true);
284 3
        $db->setEnableProfiling(true);
285
286 3
        $this->runExceptionTest($db);
287
288
        /* profiling only */
289 3
        $db->setEnableLogging(false);
290 3
        $db->setEnableProfiling(true);
291
292 3
        $this->runExceptionTest($db);
293
294
        /* logging only */
295 3
        $db->setEnableLogging(true);
296 3
        $db->setEnableProfiling(false);
297
298 3
        $this->runExceptionTest($db);
299
300
        /* disabled */
301 3
        $db->setEnableLogging(false);
302 3
        $db->setEnableProfiling(false);
303
304 3
        $this->runExceptionTest($db);
305 3
    }
306
307
    /**
308
     * @param ConnectionInterface $db
309
     */
310 3
    private function runExceptionTest(ConnectionInterface $db): void
311
    {
312 3
        $thrown = false;
313
314
        try {
315 3
            $db->createCommand('INSERT INTO qlog1(a) VALUES(:a);', [':a' => 1])->execute();
316 3
        } catch (Exception $e) {
317 3
            $this->assertStringContainsString(
0 ignored issues
show
Bug introduced by
It seems like assertStringContainsString() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

317
            $this->/** @scrutinizer ignore-call */ 
318
                   assertStringContainsString(
Loading history...
318 3
                'INSERT INTO qlog1(a) VALUES(1);',
319 3
                $e->getMessage(),
320 3
                'Exceptions message should contain raw SQL query: ' . (string) $e
321
            );
322
323 3
            $thrown = true;
324
        }
325
326 3
        $this->assertTrue($thrown, 'An exception should have been thrown by the command.');
327
328 3
        $thrown = false;
329
330
        try {
331 3
            $db->createCommand(
332 3
                'SELECT * FROM qlog1 WHERE id=:a ORDER BY nonexistingcolumn;',
333 3
                [':a' => 1]
334 3
            )->queryAll();
335 3
        } catch (Exception $e) {
336 3
            $this->assertStringContainsString(
337 3
                'SELECT * FROM qlog1 WHERE id=1 ORDER BY nonexistingcolumn;',
338 3
                $e->getMessage(),
339 3
                'Exceptions message should contain raw SQL query: ' . (string) $e
340
            );
341
342 3
            $thrown = true;
343
        }
344
345 3
        $this->assertTrue($thrown, 'An exception should have been thrown by the command.');
346 3
    }
347
348
    /**
349
     * Ensure database connection is reset on when a connection is cloned.
350
     *
351
     * Make sure each connection element has its own PDO instance i.e. own connection to the DB.
352
     * Also transaction elements should not be shared between two connections.
353
     */
354 4
    public function testClone(): void
355
    {
356 4
        $db = $this->getConnection();
357
358 4
        $this->assertNull($db->getTransaction());
359 4
        $this->assertNull($db->getPDO());
360
361 4
        $db->open();
362
363 4
        $this->assertNull($db->getTransaction());
364 4
        $this->assertNotNull($db->getPDO());
365
366 4
        $conn2 = clone $db;
367
368 4
        $this->assertNull($db->getTransaction());
369 4
        $this->assertNotNull($db->getPDO());
370
371 4
        $this->assertNull($conn2->getTransaction());
372 4
        $this->assertNull($conn2->getPDO());
373
374 4
        $db->beginTransaction();
375
376 4
        $this->assertNotNull($db->getTransaction());
377 4
        $this->assertNotNull($db->getPDO());
378
379 4
        $this->assertNull($conn2->getTransaction());
380 4
        $this->assertNull($conn2->getPDO());
381
382 4
        $conn3 = clone $db;
383
384 4
        $this->assertNotNull($db->getTransaction());
385 4
        $this->assertNotNull($db->getPDO());
386 4
        $this->assertNull($conn3->getTransaction());
387 4
        $this->assertNull($conn3->getPDO());
388 4
    }
389
}
390