Completed
Push — master ( 87170e...c34495 )
by Darío
02:39
created

TableGatewayTest::testCanExecuteDLLStatement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 17
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace DroneTest\Util;
12
13
use Drone\Db\Entity;
14
use Drone\Db\Driver\MySQL;
15
use Drone\Db\TableGateway\TableGateway;
16
use Drone\Db\TableGateway\AbstractTableGateway;
17
use PHPUnit\Framework\TestCase;
18
19
class TableGatewayTest extends TestCase
20
{
21
    /**
22
     * Database parameters
23
     */
24
    private $options = [
25
        "dbhost"       => "localhost",
26
        "dbuser"       => "root",
27
        "dbpass"       => "",
28
        "dbname"       => "test",
29
        "dbchar"       => "utf8",
30
        "dbport"       => "3306",
31
        "auto_connect" => false,
32
        "driver"       => 'Mysqli'  # needed for the DriverFactory
33
    ];
34
35
    /*
36
    |--------------------------------------------------------------------------
37
    | Establishing connections
38
    |--------------------------------------------------------------------------
39
    |
40
    | The following tests are related to the connection mechanisms and its
41
    | exceptions and returned values.
42
    |
43
    */
44
45
    /**
46
     * Tests if we can connect to the database server through a TableGateway
47
     *
48
     * @return null
49
     */
50
    public function testCanEstablishConnection()
51
    {
52
        $entity = new MyEntity();
53
        $gateway = new TableGateway($entity, ["default" => $this->options]);
54
55
        $mysqliObject = $gateway->getDb()->connect();
56
57
        $this->assertInstanceOf('\mysqli', $mysqliObject);
58
        $this->assertTrue($gateway->getDb()->isConnected());
59
    }
60
61
    /**
62
     * Tests if a failed connection throws a RuntimeException when connection exists
63
     *
64
     * @expectedException RuntimeException
65
     */
66
    public function testCannotEstablishConnectionWhenExists()
67
    {
68
        $options = $this->options;
69
        $options["dbhost"] = 'myserver';   // this server does not exists
70
71
        $entity = new MyEntity();
72
        new TableGateway($entity, ["default" => $options]);
73
    }
74
75
    /**
76
     * Tests if a failed connection throws a ConnectionException
77
     *
78
     * @expectedException Drone\Db\Driver\Exception\ConnectionException
79
     */
80
    public function testCannotEstablishConnection()
81
    {
82
        $options = $this->options;
83
        $options["dbhost"] = 'myserver';   // this server does not exists
84
85
        $entity = new MyEntity();
86
        $gateway = new TableGateway($entity, ["other" => $options]);
87
88
        try
89
        {
90
            $gateway->getDb()->connect();
91
        }
92
        catch (\Exception $e)
93
        {
94
            $this->assertNotTrue($gateway->getDb()->isConnected());
95
            throw $e;
96
        }
97
    }
98
99
    /**
100
     * Tests if we get created and not created connections
101
     *
102
     * @expectedException RuntimeException
103
     */
104
    public function testGettingConnections()
105
    {
106
        $db = AbstractTableGateway::getDriver('default');
107
        $this->assertTrue(($db instanceof MySQL));
108
        $this->assertTrue($db->isConnected());
109
110
        $db = AbstractTableGateway::getDriver('other');
111
        $this->assertTrue(($db instanceof MySQL));
112
        $this->assertNotTrue($db->isConnected());
113
114
        AbstractTableGateway::getDriver('other3');
115
    }
116
117
    /**
118
     * Tests if we can create a table gateway with an existing connection
119
     *
120
     * @return null
121
     */
122
    public function testGatewayCreationWithExistingConnection()
123
    {
124
        $options = $this->options;
125
        $options["auto_connect"] = true;
126
127
        $entity = new MyEntity();
128
        $gateway = new TableGateway($entity, "default");
129
130
        $this->assertTrue($gateway->getDb()->isConnected());
131
    }
132
133
    /*
134
    |--------------------------------------------------------------------------
135
    | Querying and Transactions
136
    |--------------------------------------------------------------------------
137
    |
138
    | The following tests are related to query and transaction operations and its
139
    | exceptions and returned values.
140
    |
141
    */
142
143
    /**
144
     * Tests if we can execute DDL statements
145
     *
146
     * @return null
147
     */
148
    public function testCanExecuteDLLStatement()
149
    {
150
        $options = $this->options;
151
        $options["auto_connect"] = true;
152
153
        $entity = new MyEntity();
154
        $gateway = new MyEntityGateway($entity, "default");
155
156
        $result = $gateway->create();
157
158
        # mysqli
159
        $this->assertTrue(is_object($result));
160
161
        # properties modified by execute() method
162
        $this->assertEquals(0, $gateway->getDb()->getNumRows());
163
        $this->assertEquals(0, $gateway->getDb()->getNumFields());
164
        $this->assertEquals(0, $gateway->getDb()->getRowsAffected());
165
    }
166
167
    /**
168
     * Tests if we can execute DML statements
169
     *
170
     * @return null
171
     */
172
    public function testCanExecuteDMLStatement()
173
    {
174
        $options = $this->options;
175
        $options["auto_connect"] = true;
176
177
        $entity = new MyEntity();
178
        $gateway = new MyEntityGateway($entity, "default");
179
180
        # mysqli
181
        $result = $gateway->customDML(); // insert statement
182
183
        $this->assertTrue(is_object($result));
184
185
        # properties modified by execute() method
186
        $this->assertEquals(0, $gateway->getDb()->getNumRows());
187
        $this->assertEquals(0, $gateway->getDb()->getNumFields());
188
        $this->assertEquals(1, $gateway->getDb()->getRowsAffected());
189
    }
190
191
    /**
192
     * Tests if a wrong query execution throws an InvalidQueryException
193
     *
194
     * @expectedException Drone\Db\Driver\Exception\InvalidQueryException
195
     */
196
    public function testGettingInvalidQueryException()
197
    {
198
        $options = $this->options;
199
        $options["auto_connect"] = true;
200
201
        $entity = new MyEntity();
202
        $gateway = new MyEntityGateway($entity, "default");
203
204
        $gateway->wrongDML();
205
    }
206
207
    /**
208
     * Tests getting results
209
     *
210
     * @return null
211
     */
212
    public function testGettingResults()
213
    {
214
        $options = $this->options;
215
        $options["auto_connect"] = true;
216
217
        $entity = new MyEntity();
218
        $gateway = new MyEntityGateway($entity, "default");
219
220
        $rows = $gateway->getResults();
221
222
        # get only the first
223
        $row = array_shift($rows);
224
225
        $this->assertArrayHasKey("ID", $row);
226
        $this->assertArrayHasKey("DESCRIPTION", $row);
227
228
        # properties modified by execute() method
229
        $this->assertEquals(1, $gateway->getDb()->getNumRows());
230
        $this->assertEquals(2, $gateway->getDb()->getNumFields());
231
        $this->assertEquals(0, $gateway->getDb()->getRowsAffected());
232
    }
233
234
    # AS YOU CAN SEE IN THE ABOVE TEST, IT'S EASY TO ACCESS TO THE DRIVER (HERE MYSQL) USING THE
235
    # getDb() METHOD. A COMPLETE TEST FOR A DRIVER IS AVAILABLE IN MySQLTest.php. ALL TRANSACTION
236
    # BEHAVIOR OF TABLE GATEWAY IS RELATED TO THE DRIVER. ONLY GET THE DRIVER AND LET'S DO IT.
237
238
    /*
239
    |--------------------------------------------------------------------------
240
    | TABLE GATEWAY
241
    |--------------------------------------------------------------------------
242
    |
243
    | The following tests are related to table gateway.
244
    |
245
    */
246
247
    /**
248
     * Tests if we can execute INSERT statements through the TableGateway
249
     *
250
     * @return null
251
     */
252
    public function testINSERTING()
253
    {
254
        $options = $this->options;
255
        $options["auto_connect"] = true;
256
257
        $entity = new MyEntity();
258
259
        # Here we can use the generic table gateway or ours
260
        $gateway = new TableGateway($entity, "default");
261
262
        $result = $gateway->insert(["ID" => 500, "DESCRIPTION" => "NEW ELEMENT ONE"]);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
263
        $result = $gateway->insert(["ID" => 501, "DESCRIPTION" => "NEW ELEMENT TWO"]);
264
265
        $this->assertTrue(is_object($result));
266
267
        # properties modified by execute() method
268
        $this->assertEquals(0, $gateway->getDb()->getNumRows());
269
        $this->assertEquals(0, $gateway->getDb()->getNumFields());
270
271
        # here 1 is the latest affected row, could be 2 if auto_commit were false
272
        $this->assertEquals(1, $gateway->getDb()->getRowsAffected());
273
    }
274
275
    /**
276
     * Tests if no data to insert throws a LogicException
277
     *
278
     * @expectedException LogicException
279
     */
280
    public function testGettingLogicExceptionInEmptyInsertStatement()
281
    {
282
        $options = $this->options;
283
        $options["auto_connect"] = true;
284
285
        $entity = new MyEntity();
286
        $gateway = new MyEntityGateway($entity, "default");
287
288
        $gateway->insert([]);
289
    }
290
291
    /**
292
     * Tests if we can execute UPDATE statements through the TableGateway
293
     *
294
     * @return null
295
     */
296
    public function testUPDATING()
297
    {
298
        $options = $this->options;
299
        $options["auto_connect"] = true;
300
301
        $entity = new MyEntity();
302
303
        # Here we can use the generic table gateway or ours
304
        $gateway = new TableGateway($entity, "default");
305
306
        $result = $gateway->update(["DESCRIPTION" => "NEW ELEMENT MODIFIED"], ["ID" => 500]);
307
308
        $this->assertTrue(is_object($result));
309
310
        # properties modified by execute() method
311
        $this->assertEquals(0, $gateway->getDb()->getNumRows());
312
        $this->assertEquals(0, $gateway->getDb()->getNumFields());
313
        $this->assertEquals(1, $gateway->getDb()->getRowsAffected());
314
    }
315
316
    /**
317
     * Tests if no SET clause throws a LogicException in update statements
318
     *
319
     * @expectedException LogicException
320
     */
321
    public function testGettingLogicExceptionWhenUpdatingWithoutSETClause()
322
    {
323
        $options = $this->options;
324
        $options["auto_connect"] = true;
325
326
        $entity = new MyEntity();
327
        $gateway = new MyEntityGateway($entity, "default");
328
329
        $gateway->update([], ["ID" => 500]);
330
    }
331
332
    /**
333
     * Tests if no WHERE clause throws a SecurityException in update statements
334
     *
335
     * @expectedException Drone\Exception\SecurityException
336
     */
337
    public function testGettingSecurityExceptionWhenUpdatingWithoutWHEREClause()
338
    {
339
        $options = $this->options;
340
        $options["auto_connect"] = true;
341
342
        $entity = new MyEntity();
343
        $gateway = new MyEntityGateway($entity, "default");
344
345
        $gateway->update(["DESCRIPTION" => "NEW ELEMENT MODIFIED"], []);
346
    }
347
348
    /**
349
     * Tests if we can execute DELETE statements through the TableGateway
350
     *
351
     * @return null
352
     */
353
    public function testDELETING()
354
    {
355
        $options = $this->options;
356
        $options["auto_connect"] = true;
357
358
        $entity = new MyEntity();
359
360
        # Here we can use the generic table gateway or ours
361
        $gateway = new TableGateway($entity, "default");
362
363
        $result = $gateway->delete(["ID" => 500]);
364
365
        $this->assertTrue(is_object($result));
366
367
        # properties modified by execute() method
368
        $this->assertEquals(0, $gateway->getDb()->getNumRows());
369
        $this->assertEquals(0, $gateway->getDb()->getNumFields());
370
        $this->assertEquals(1, $gateway->getDb()->getRowsAffected());
371
    }
372
373
    /**
374
     * Tests if no WHERE clause throws a SecurityException in delete statements
375
     *
376
     * @expectedException Drone\Exception\SecurityException
377
     */
378
    public function testGettingSecurityExceptionWhenDeletingWithoutWHEREClause()
379
    {
380
        $options = $this->options;
381
        $options["auto_connect"] = true;
382
383
        $entity = new MyEntity();
384
        $gateway = new MyEntityGateway($entity, "default");
385
386
        $gateway->delete([]);
387
    }
388
389
    /**
390
     * Tests if we can execute SELECT statements through the TableGateway
391
     *
392
     * @return null
393
     */
394
    public function testSELECTING()
395
    {
396
        $options = $this->options;
397
        $options["auto_connect"] = true;
398
399
        $entity = new MyEntity();
400
401
        # Here we can use the generic table gateway or ours
402
        $gateway = new TableGateway($entity, "default");
403
404
        $rows = $gateway->select(["ID" => 501]);
405
406
        $this->assertTrue(is_array($rows));
407
408
        # get only the first
409
        $row = array_shift($rows);
410
411
        $this->assertArrayHasKey("ID", $row);
412
        $this->assertArrayHasKey("DESCRIPTION", $row);
413
414
        # properties modified by execute() method
415
        $this->assertEquals(1, $gateway->getDb()->getNumRows());
416
        $this->assertEquals(2, $gateway->getDb()->getNumFields());
417
        $this->assertEquals(0, $gateway->getDb()->getRowsAffected());
418
419
        $this->endTests();
420
    }
421
422
    /**
423
     * Function to leave all in order, you can execute tests again without problems.
424
     *
425
     * @return null
426
     */
427
    private function endTests()
428
    {
429
        $options = $this->options;
430
        $options["auto_connect"] = true;
431
432
        $entity = new MyEntity();
433
        $gateway = new MyEntityGateway($entity, "default");
434
435
        # remove all work
436
        $gateway->drop();
437
    }
438
}
439
440
class MyEntity extends Entity
441
{
442
    public $ID;
443
    public $DESCRIPTION;
444
445
    public function __construct($data = [])
446
    {
447
        parent::__construct($data);
448
        $this->setTableName("MYTABLE");
449
   }
450
}
451
452
class MyEntityGateway extends TableGateway
453
{
454
    public function create()
455
    {
456
        $sql = "CREATE TABLE MYTABLE (ID INTEGER(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, DESCRIPTION VARCHAR(100))";
457
        return $this->getDb()->execute($sql);
458
    }
459
460
    public function drop()
461
    {
462
        $sql = "DROP TABLE MYTABLE";
463
        return $this->getDb()->execute($sql);
464
    }
465
466
    public function customDML()
467
    {
468
        $sql = "INSERT INTO MYTABLE VALUES(1000, 'Some data')";
469
        return $this->getDb()->execute($sql);
470
    }
471
472
    public function wrongDML()
473
    {
474
        $sql = "INSERT INTO MYTABLE (DESCRIPTION, WRONG) VALUES ('Hello world!')";
475
        return $this->getDb()->execute($sql);
476
    }
477
478
    public function getResults()
479
    {
480
        $sql = "SELECT * FROM MYTABLE WHERE ID = 1000";
481
        $this->getDb()->execute($sql);
482
        return $this->getDb()->getArrayResult();
483
    }
484
}