Skip to content

Commit c70b225

Browse files
committed
Add tests for query
1 parent e151ff4 commit c70b225

File tree

10 files changed

+232
-30
lines changed

10 files changed

+232
-30
lines changed

src/Query.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public function generateModels(string $alias = '', array $relationships = []): \
137137
}
138138

139139
foreach ($this->fetchResult() as $row) {
140-
yield $schema->createModel($row, $prefix, $modelRelationships);
140+
yield $schema->createModelFromRow($row, $prefix, $modelRelationships);
141141
}
142142
}
143143

src/Record.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public function getSchema(): Schema
9494
public function getModel(): Model
9595
{
9696
if ($this->model === null) {
97-
$this->model = $this->schema->getModel($this);
97+
$this->model = $this->schema->createModel($this);
9898
}
9999

100100
return $this->model;

src/RelationshipFiller.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private function getCachedRecord(int $schemaId, Schema $schema, array $row): Rec
152152
return $this->cache[$schemaId][$recordId];
153153
}
154154

155-
$record = $schema->getRecord($row);
155+
$record = $schema->createRecordFromValues($row);
156156
$this->cache[$schemaId][$recordId] = $record;
157157
return $record;
158158
}

src/Repository.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected function find(Schema $schema, array $conditions, array $order = [], in
2727
$models = [];
2828

2929
foreach ($result as $row) {
30-
$models[] = $schema->createModel($row);
30+
$models[] = $schema->createModelFromRow($row);
3131
}
3232

3333
return $models;
@@ -42,7 +42,7 @@ protected function findOne(Schema $schema, array $conditions): ?Model
4242
$result->setFetchMode(\PDO::FETCH_ASSOC);
4343
$row = $result->fetch();
4444

45-
return $row ? $schema->createModel($row) : null;
45+
return $row ? $schema->createModelFromRow($row) : null;
4646
}
4747

4848
protected function findByPrimaryKey(Schema $schema, $values): ?Model

src/Schema.php

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,33 +96,20 @@ private function getSchema(string $name): Schema
9696
return $this->container->get($name);
9797
}
9898

99-
public function getRecord(array $values): Record
100-
{
101-
$record = $this->createRecord();
102-
$record->setDatabaseValues($values);
103-
104-
return $record;
105-
}
106-
107-
public function getModel(Record $record): Model
99+
public function createRecord(Model $model = null): Record
108100
{
109-
return $this->model::createFromDatabaseRecord($record);
101+
return new Record($this, $model);
110102
}
111103

112-
public function createModel(array $row, string $prefix = '', array $relationships = []): Model
104+
public function createRecordFromValues(array $values): Record
113105
{
114-
$record = $this->getRecord($this->getPrefixedFields($row, $prefix));
115-
116-
foreach ($relationships as $key => $name) {
117-
$relationship = $this->getRelationship($name);
118-
$schema = $relationship->getReferencedSchema();
119-
$relationship->fillSingleRecord($record, $schema->getRecord($schema->getPrefixedFields($row, $key)));
120-
}
106+
$record = $this->createRecord();
107+
$record->setDatabaseValues($values);
121108

122-
return $record->getModel();
109+
return $record;
123110
}
124111

125-
private function getPrefixedFields(array $row, string $prefix): array
112+
public function createRecordFromRow(array $row, string $prefix = ''): Record
126113
{
127114
$values = [];
128115

@@ -134,11 +121,24 @@ private function getPrefixedFields(array $row, string $prefix): array
134121
}
135122
}
136123

137-
return $values;
124+
return $this->createRecordFromValues($values);
138125
}
139126

140-
public function createRecord(Model $model = null): Record
127+
public function createModel(Record $record): Model
141128
{
142-
return new Record($this, $model);
129+
return $this->model::createFromDatabaseRecord($record);
130+
}
131+
132+
public function createModelFromRow(array $row, string $prefix = '', array $relationships = []): Model
133+
{
134+
$record = $this->createRecordFromRow($row, $prefix);
135+
136+
foreach ($relationships as $key => $name) {
137+
$relationship = $this->getRelationship($name);
138+
$schema = $relationship->getReferencedSchema();
139+
$relationship->fillSingleRecord($record, $schema->createRecordFromRow($row, $key));
140+
}
141+
142+
return $record->getModel();
143143
}
144144
}

tests/helpers/MockPdoStatement.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Simply\Database\Test;
4+
5+
/**
6+
* MockPdoStatement.
7+
* @author Riikka Kalliomäki <[email protected]>
8+
* @copyright Copyright (c) 2018 Riikka Kalliomäki
9+
* @license http://opensource.org/licenses/mit-license.php MIT License
10+
*/
11+
class MockPdoStatement extends \PDOStatement implements \IteratorAggregate
12+
{
13+
public function getIterator()
14+
{
15+
throw new \LogicException('This method should be mocked');
16+
}
17+
}

tests/helpers/TestCase/IntegrationTestCase.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,11 @@ public function testCustomQuery()
328328
sort($ages);
329329

330330
$this->assertSame([35, 41, 44, 45], $ages);
331+
$this->assertSame(1, $repository->countYoungerThan(40));
332+
$this->assertSame(5, $repository->countYoungerThan(50));
331333
}
332334

333-
public function testIterationWithRelation()
335+
public function testIterationWithOneToOneRelation()
334336
{
335337
$repository = $this->getTestPersonRepository();
336338
$this->setUpFamily($repository);
@@ -350,4 +352,18 @@ public function testIterationWithRelation()
350352

351353
$this->assertSame(4, $count);
352354
}
355+
356+
public function testIterationWithRelation()
357+
{
358+
$repository = $this->getTestPersonRepository();
359+
$this->setUpFamily($repository);
360+
$count = 0;
361+
362+
foreach ($repository->iterateWithHouse() as $person) {
363+
$count++;
364+
$this->assertSame('Anonymous Street', $person->getHome()->getStreet());
365+
}
366+
367+
$this->assertSame(4, $count);
368+
}
353369
}

tests/helpers/TestRepository.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ public function findYoungerThan(int $age): array
132132
->fetchModels();
133133
}
134134

135+
public function countYoungerThan(int $age): int
136+
{
137+
return \count($this->query('SELECT id FROM {p.table} WHERE age < :age')
138+
->withSchema($this->personSchema, 'p')
139+
->withParameters(['age' => $age])
140+
->fetchRows());
141+
}
142+
135143
/**
136144
* @return \Generator|TestPersonModel[]
137145
*/
@@ -142,6 +150,31 @@ public function iterateWithSpouse(): \Generator
142150
)
143151
->withSchema($this->personSchema, 'p')
144152
->withSchema($this->personSchema, 's')
145-
->generateModels('p', ['s' => 'spouse']);
153+
->generateCallback(function (array $row): TestPersonModel {
154+
$person = $this->personSchema->createRecordFromRow($row, 'p_');
155+
$spouse = $this->personSchema->createRecordFromRow($row, 's_');
156+
157+
$relationship = $this->personSchema->getRelationship('spouse');
158+
$relationship->fillSingleRecord($person, $spouse);
159+
160+
if (!$spouse->isEmpty()) {
161+
$relationship->fillSingleRecord($spouse, $person);
162+
}
163+
164+
return $person->getModel();
165+
});
166+
}
167+
168+
/**
169+
* @return \Generator|TestPersonModel[]
170+
*/
171+
public function iterateWithHouse(): \Generator
172+
{
173+
return $this->query(
174+
'SELECT {p.fields}, {h.fields} FROM {p.table} LEFT JOIN {h.table} ON h.id = p.home_id'
175+
)
176+
->withSchema($this->personSchema, 'p')
177+
->withSchema($this->houseSchema, 'h')
178+
->generateModels('p', ['h' => 'home']);
146179
}
147180
}

tests/tests/QueryTest.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace Simply\Database;
4+
5+
use Simply\Database\Connection\MySqlConnection;
6+
use Simply\Database\Test\MockPdoStatement;
7+
use Simply\Database\Test\TestCase\UnitTestCase;
8+
use Simply\Database\Test\TestHouseModel;
9+
10+
/**
11+
* QueryTest.
12+
* @author Riikka Kalliomäki <[email protected]>
13+
* @copyright Copyright (c) 2018 Riikka Kalliomäki
14+
* @license http://opensource.org/licenses/mit-license.php MIT License
15+
*/
16+
class QueryTest extends UnitTestCase
17+
{
18+
public function testGenerateFromInvalidSchema(): void
19+
{
20+
$query = $this->getQuery('', []);
21+
22+
$query = $query->withSchema($this->getPersonSchema(), 'person');
23+
$query = $query->withoutSchemas();
24+
25+
$this->expectException(\InvalidArgumentException::class);
26+
$query->fetchModels('person');
27+
}
28+
29+
public function testGenerateFromOneSchema(): void
30+
{
31+
$data = [['h_id' => 1, 'h_street' => 'Street Name']];
32+
$query = $this->getQuery('SELECT {h.fields} FROM {h.table}', $data)
33+
->withSchema($this->getPersonSchema()->getRelationship('home')->getReferencedSchema(), 'h');
34+
35+
/** @var TestHouseModel[] $houses */
36+
$houses = $query->fetchModels();
37+
38+
$this->assertCount(1, $houses);
39+
$this->assertSame('Street Name', $houses[0]->getStreet());
40+
}
41+
42+
public function testFetchCallback(): void
43+
{
44+
$data = [['age' => '5'], ['age' => '3']];
45+
46+
$ages = $this->getQuery('SELECT age FROM {table}', $data)
47+
->withSchema($this->getPersonSchema())
48+
->fetchCallback(function (array $row): int {
49+
return $row['age'];
50+
});
51+
52+
$this->assertSame([5, 3], $ages);
53+
}
54+
55+
public function testNoParametersPassed(): void
56+
{
57+
$schema = $this->getPersonSchema();
58+
59+
$connection = $this->getMockBuilder(MySqlConnection::class)
60+
->disableOriginalConstructor()
61+
->setMethods(['query'])
62+
->getMock();
63+
$connection->expects($this->once())
64+
->method('query')
65+
->with("SELECT age FROM `{$schema->getTable()}`", [])
66+
->willReturn($this->getMockStatement([]));
67+
68+
$query = new Query($connection, 'SELECT age FROM {table}');
69+
$query = $query->withSchema($schema);
70+
$query = $query->withParameters(['name' => 'value']);
71+
$query = $query->withoutParameters();
72+
73+
$this->assertCount(0, $query->fetchRows());
74+
}
75+
76+
private function getQuery(string $sql, array $rows): Query
77+
{
78+
$connection = $this->getMockBuilder(MySqlConnection::class)
79+
->disableOriginalConstructor()
80+
->setMethods(['query'])
81+
->getMock();
82+
$connection->expects($this->atMost(1))->method('query')->willReturn($this->getMockStatement($rows));
83+
84+
return new Query($connection, $sql);
85+
}
86+
87+
public function getMockStatement(array $rows): \PDOStatement
88+
{
89+
$statement = $this->getMockBuilder(MockPdoStatement::class)
90+
->disableOriginalConstructor()
91+
->getMock();
92+
93+
$statement->expects($this->atMost(1))->method('getIterator')->willReturn(new \ArrayIterator($rows));
94+
95+
return $statement;
96+
}
97+
}

tests/tests/SchemaTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,43 @@ public function testFillingWithNullValues(): void
205205
$this->assertSame([$personA], $personB->getReferencedRecords('spouse'));
206206
$this->assertSame([], $personC->getReferencedRecords('spouse'));
207207
}
208+
209+
public function testTryFillingNonUniqueSingleRelatinoship()
210+
{
211+
$schema = $this->getPersonSchema();
212+
$values = [];
213+
214+
foreach ($schema->getFields() as $field) {
215+
$values['p_' . $field] = null;
216+
}
217+
218+
$values['p_id'] = 1;
219+
220+
foreach ($schema->getRelationship('parents')->getReferencedSchema()->getFields() as $field) {
221+
$values['r_' . $field] = null;
222+
}
223+
224+
$values['r_child_id'] = 1;
225+
226+
$this->expectException(\LogicException::class);
227+
$schema->createModelFromRow($values, 'p_', ['r_' => 'parents']);
228+
}
229+
230+
public function testTryFillingANonRelatedRecord()
231+
{
232+
$schema = $this->getPersonSchema();
233+
$values = [];
234+
235+
foreach ($schema->getFields() as $field) {
236+
$values['p_' . $field] = null;
237+
$values['s_' . $field] = null;
238+
}
239+
240+
$values['p_id'] = 1;
241+
$values['p_spouse_id'] = 2;
242+
$values['s_id'] = 3;
243+
244+
$this->expectException(\LogicException::class);
245+
$schema->createModelFromRow($values, 'p_', ['s_' => 'spouse']);
246+
}
208247
}

0 commit comments

Comments
 (0)