Issues (259)

Tests/Mapping/ObjectMappingTest.php (11 issues)

1
<?php
2
/**
3
 * Copyright (C) 2017  Gerrit Addiks.
4
 * This package (including this file) was released under the terms of the GPL-3.0.
5
 * You should have received a copy of the GNU General Public License along with this program.
6
 * If not, see <http://www.gnu.org/licenses/> or send me a mail so i can send you a copy.
7
 * @license GPL-3.0
8
 * @author Gerrit Addiks <[email protected]>
9
 */
10
11
namespace Addiks\RDMBundle\Tests\Mapping;
12
13
use PHPUnit\Framework\TestCase;
14
use Addiks\RDMBundle\Mapping\ObjectMapping;
15
use Addiks\RDMBundle\Mapping\CallDefinitionInterface;
16
use Addiks\RDMBundle\Tests\ValueObjectExample;
17
use Addiks\RDMBundle\Mapping\MappingInterface;
18
use Doctrine\DBAL\Schema\Column;
19
use Addiks\RDMBundle\Exception\FailedRDMAssertionExceptionInterface;
20
use Addiks\RDMBundle\Hydration\HydrationContextInterface;
21
use Addiks\RDMBundle\Tests\Hydration\EntityExample;
22
use Doctrine\DBAL\Types\Type;
23
use Doctrine\ORM\EntityManagerInterface;
24
use Doctrine\DBAL\Connection;
25
use Doctrine\DBAL\Platforms\AbstractPlatform;
26
use ReflectionClass;
27
use Symfony\Component\DependencyInjection\ContainerInterface;
28
29
final class ObjectMappingTest extends TestCase
30
{
31
32
    /**
33
     * @var ObjectMapping
34
     */
35
    private $objectMapping;
36
37
    /**
38
     * @var CallDefinitionInterface
39
     */
40
    private $factory;
41
42
    /**
43
     * @var CallDefinitionInterface
44
     */
45
    private $serializer;
46
47
    /**
48
     * @var MappingInterface
49
     */
50
    private $fieldMappingA;
51
52
    /**
53
     * @var MappingInterface
54
     */
55
    private $fieldMappingB;
56
57
    /**
58
     * @var Column
59
     */
60
    private $column;
61
62
    public function setUp(
63
        string $className = ValueObjectExample::class,
64
        bool $hasFieldMappingB = true,
65
        bool $useFactory = true,
66
        bool $useSerializer = true,
67
        string $id = "some_id",
68
        string $referenceId = "some_reference",
69
        string $firstMappingName = "lorem"
70
    ): void {
71
        $this->factory = $this->createMock(CallDefinitionInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Addiks...nitionInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Addiks\RDMBundle\Mapping\CallDefinitionInterface of property $factory.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
72
        $this->serializer = $this->createMock(CallDefinitionInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Addiks...nitionInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Addiks\RDMBundle\Mapping\CallDefinitionInterface of property $serializer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
73
        $this->fieldMappingA = $this->createMock(MappingInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Addiks...appingInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Addiks\RDMBundle\Mapping\MappingInterface of property $fieldMappingA.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
74
        $this->fieldMappingB = $this->createMock(MappingInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Addiks...appingInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Addiks\RDMBundle\Mapping\MappingInterface of property $fieldMappingB.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
75
        $this->column = $this->createMock(Column::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Doctri...L\Schema\Column::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Doctrine\DBAL\Schema\Column of property $column.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
76
77
        /** @var array<string,MappingInterface> $fieldMappings */
78
        $fieldMappings = [
79
            $firstMappingName => $this->fieldMappingA,
80
        ];
81
82
        if ($hasFieldMappingB) {
83
            $fieldMappings['dolor'] = $this->fieldMappingB;
84
        }
85
86
        /** @var CallDefinitionInterface|null $factory */
87
        $factory = null;
88
89
        /** @var CallDefinitionInterface|null $serializer */
90
        $serializer = null;
91
92
        if ($useFactory) {
93
            $factory = $this->factory;
94
        }
95
96
        if ($useSerializer) {
97
            $serializer = $this->serializer;
98
        }
99
100
        $this->objectMapping = new ObjectMapping(
101
            $className,
102
            $fieldMappings,
103
            $this->column,
104
            "some cool origin",
105
            $factory,
106
            $serializer,
107
            $id,
108
            $referenceId
109
        );
110
    }
111
112
    /**
113
     * @test
114
     */
115
    public function shouldStoreClassName()
116
    {
117
        $this->assertEquals(ValueObjectExample::class, $this->objectMapping->getClassName());
118
    }
119
120
    /**
121
     * @test
122
     */
123
    public function shouldStoreFieldMappings()
124
    {
125
        $this->assertEquals([
126
            'lorem' => $this->createMock(MappingInterface::class),
127
            'dolor' => $this->createMock(MappingInterface::class),
128
        ], $this->objectMapping->getFieldMappings());
129
    }
130
131
    /**
132
     * @test
133
     */
134
    public function shouldStoreOrigin()
135
    {
136
        $this->assertEquals("some cool origin", $this->objectMapping->describeOrigin());
137
    }
138
139
    /**
140
     * @test
141
     */
142
    public function shouldStoreDBALColumn()
143
    {
144
        $this->assertSame($this->column, $this->objectMapping->getDBALColumn());
145
    }
146
147
    /**
148
     * @test
149
     */
150
    public function shouldStoreId()
151
    {
152
        $this->assertSame("some_id", $this->objectMapping->getId());
153
    }
154
155
    /**
156
     * @test
157
     */
158
    public function shouldStoreReferenceId()
159
    {
160
        $this->assertSame("some_reference", $this->objectMapping->getReferencedId());
161
    }
162
163
    /**
164
     * @test
165
     */
166
    public function shouldCollectDBALColumns()
167
    {
168
        /** @var Column $columnA */
169
        $columnA = $this->createMock(Column::class);
170
171
        /** @var Column $columnB */
172
        $columnB = $this->createMock(Column::class);
173
174
        /** @var array<Column> $expectedColumns */
175
        $expectedColumns = [$columnA, $columnB, $this->column];
176
177
        $this->fieldMappingA->method('collectDBALColumns')->willReturn([$columnA]);
0 ignored issues
show
The method method() does not exist on Addiks\RDMBundle\Mapping\MappingInterface. ( Ignorable by Annotation )

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

177
        $this->fieldMappingA->/** @scrutinizer ignore-call */ 
178
                              method('collectDBALColumns')->willReturn([$columnA]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
178
        $this->fieldMappingB->method('collectDBALColumns')->willReturn([$columnB]);
179
180
        $this->assertEquals($expectedColumns, $this->objectMapping->collectDBALColumns());
181
    }
182
183
    /**
184
     * @test
185
     */
186
    public function shouldStoreFactory()
187
    {
188
        $this->assertSame($this->factory, $this->objectMapping->getFactory());
189
    }
190
191
    /**
192
     * @test
193
     */
194
    public function shouldStoreSerializer()
195
    {
196
        $this->assertSame($this->serializer, $this->objectMapping->getSerializer());
197
    }
198
199
    /**
200
     * @test
201
     */
202
    public function shouldResolveObjectValue()
203
    {
204
        $this->setUp(ValueObjectExample::class, false, true, false, "some_id", "", "amet");
205
206
        /** @var ValueObjectExample $object */
207
        $object = $this->createMock(ValueObjectExample::class);
208
209
        $this->column->expects($this->once())->method("getName")->willReturn("some_column");
210
211
        /** @var HydrationContextInterface $context */
212
        $context = $this->createMock(HydrationContextInterface::class);
213
        $context->method('getEntityClass')->willReturn(EntityExample::class);
0 ignored issues
show
The method method() does not exist on Addiks\RDMBundle\Hydrati...drationContextInterface. ( Ignorable by Annotation )

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

213
        $context->/** @scrutinizer ignore-call */ 
214
                  method('getEntityClass')->willReturn(EntityExample::class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
214
        $context->expects($this->once())->method('registerValue')->with(
0 ignored issues
show
The method expects() does not exist on Addiks\RDMBundle\Hydrati...drationContextInterface. ( Ignorable by Annotation )

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

214
        $context->/** @scrutinizer ignore-call */ 
215
                  expects($this->once())->method('registerValue')->with(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
215
            "some_id",
216
            $object
217
        );
218
219
        /** @var mixed $dataFromAdditionalColumns */
220
        $dataFromAdditionalColumns = array(
221
            'lorem' => 'ipsum',
222
            'dolor' => 'sit amet',
223
            'amet'  => 'EXPECTED',
224
        );
225
226
        $this->factory->method('execute')->willReturn($object);
227
228
        $this->fieldMappingA->expects($this->once())->method('resolveValue')->with(
229
            $this->equalTo($context),
230
            $this->equalTo([
231
                'amet'  => 'EXPECTED',
232
                'lorem' => 'ipsum',
233
                'dolor' => 'sit amet',
234
            ])
235
        )->willReturn("FOO BAR BAZ");
236
237
        /** @var mixed $actualObject */
238
        $actualObject = $this->objectMapping->resolveValue($context, $dataFromAdditionalColumns);
239
240
        $this->assertSame($actualObject, $object);
241
242
        $reflectionClass = new ReflectionClass(ValueObjectExample::class);
243
244
        /** @var ReflectionProperty $reflectionProperty */
245
        $reflectionProperty = $reflectionClass->getProperty("amet");
246
        $reflectionProperty->setAccessible(true);
247
248
        $this->assertEquals("FOO BAR BAZ", $reflectionProperty->getValue($object));
249
    }
250
251
    /**
252
     * @test
253
     */
254
    public function shouldNotLoadFactoryArgumentsWhenDataGiven()
255
    {
256
        $this->setUp(ValueObjectExample::class, false, true, false, "some_id", "");
257
258
        /** @var ValueObjectExample $object */
259
        $object = $this->createMock(ValueObjectExample::class);
260
261
        $this->column->expects($this->never())->method("getName");
262
263
        /** @var HydrationContextInterface $context */
264
        $context = $this->createMock(HydrationContextInterface::class);
265
        $context->method('getEntityClass')->willReturn(EntityExample::class);
266
        $context->expects($this->once())->method('registerValue')->with(
267
            "some_id",
268
            $object
269
        );
270
271
        $this->factory->method('execute')->willReturn($object);
272
273
        /** @var mixed $dataFromAdditionalColumns */
274
        $dataFromAdditionalColumns = array(
275
            'lorem' => 'ipsum',
276
            'dolor' => 'sit amet',
277
            '' => 'foo'
278
        );
279
280
        $this->fieldMappingA->method('resolveValue')->willReturn("FOO BAR BAZ");
281
282
        $this->objectMapping->resolveValue($context, $dataFromAdditionalColumns);
283
    }
284
285
    /**
286
     * @test
287
     */
288
    public function shouldRevertObjectValue()
289
    {
290
        $this->setUp(ValueObjectExample::class, false, false, false, "some_id", "", "amet");
291
292
        /** @var HydrationContextInterface $context */
293
        $context = $this->createMock(HydrationContextInterface::class);
294
        $context->method('getEntityClass')->willReturn(EntityExample::class);
295
        $context->method('getEntityManager')->willReturn($this->createEntityManagerMock());
296
297
        $actualObject = new ValueObjectExample('foo', 'sit amet');
298
        $actualObject->setAmet('EXPECTED');
299
300
        $this->fieldMappingA->method('revertValue')->will($this->returnValueMap([
301
            [$context, 'sit amet', ['amet' => "FOO BAR BAZ"]],
302
            [$context, 'EXPECTED', ['amet' => "QWE ASD YXC"]],
303
        ]));
304
305
        /** @var Type $type */
306
        $type = $this->createMock(Type::class);
307
308
        $this->column->method('getType')->willReturn($type);
309
310
        /** @var array $actualData */
311
        $actualData = $this->objectMapping->revertValue($context, $actualObject);
312
313
        $this->assertEquals(['amet' => "QWE ASD YXC"], $actualData);
314
    }
315
316
    /**
317
     * @test
318
     */
319
    public function shouldFailAssertionOnWrongObject()
320
    {
321
        $this->setUp(ValueObjectExample::class);
322
323
        $dataFromAdditionalColumns = array(
324
            'lorem' => 'ipsum',
325
            'dolor' => 'sit amet',
326
        );
327
328
        /** @var mixed $actualValue */
329
        $actualValue = $this->createMock(EntityExample::class);
330
331
        $this->expectException(FailedRDMAssertionExceptionInterface::class);
332
333
        /** @var HydrationContextInterface $context */
334
        $context = $this->createMock(HydrationContextInterface::class);
335
        $context->method('getEntityClass')->willReturn(EntityExample::class);
336
337
        $this->objectMapping->assertValue($context, $dataFromAdditionalColumns, $actualValue);
338
    }
339
340
    private function createEntityManagerMock(): EntityManagerInterface
341
    {
342
        /** @var EntityManagerInterface $entityManager */
343
        $entityManager = $this->createMock(EntityManagerInterface::class);
344
345
        /** @var Connection $connection */
346
        $connection = $this->createMock(Connection::class);
347
348
        $entityManager->method('getConnection')->willReturn($connection);
0 ignored issues
show
The method method() does not exist on Doctrine\ORM\EntityManagerInterface. ( Ignorable by Annotation )

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

348
        $entityManager->/** @scrutinizer ignore-call */ 
349
                        method('getConnection')->willReturn($connection);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
349
350
        /** @var AbstractPlatform $platform */
351
        $platform = $this->createMock(AbstractPlatform::class);
352
353
        $connection->method('getDatabasePlatform')->willReturn($platform);
0 ignored issues
show
The method method() does not exist on Doctrine\DBAL\Connection. ( Ignorable by Annotation )

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

353
        $connection->/** @scrutinizer ignore-call */ 
354
                     method('getDatabasePlatform')->willReturn($platform);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
354
355
        return $entityManager;
356
    }
357
358
    /**
359
     * @test
360
     */
361
    public function shouldWakeUpInnerMapping()
362
    {
363
        /** @var ContainerInterface $container */
364
        $container = $this->createMock(ContainerInterface::class);
365
366
        $this->factory->expects($this->once())->method("wakeUpCall")->with(
0 ignored issues
show
The method expects() does not exist on Addiks\RDMBundle\Mapping\CallDefinitionInterface. ( Ignorable by Annotation )

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

366
        $this->factory->/** @scrutinizer ignore-call */ 
367
                        expects($this->once())->method("wakeUpCall")->with(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
367
            $this->equalTo($container)
368
        );
369
370
        $this->serializer->expects($this->once())->method("wakeUpCall")->with(
371
            $this->equalTo($container)
372
        );
373
374
        $this->objectMapping->wakeUpMapping($container);
375
    }
376
377
}
378