Completed
Push — master ( 2f25cf...59cc7f )
by Marco
43:54 queued 18:55
created

PropertiesTest::testOnlyNullableProperties()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 63
c 0
b 0
f 0
rs 8.8072
cc 1
nc 1
nop 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 ProxyManagerTest\ProxyGenerator\Util;
6
7
use PHPUnit\Framework\TestCase;
8
use ProxyManager\ProxyGenerator\Util\Properties;
9
use ProxyManagerTestAsset\ClassWithAbstractProtectedMethod;
10
use ProxyManagerTestAsset\ClassWithAbstractPublicMethod;
11
use ProxyManagerTestAsset\ClassWithCollidingPrivateInheritedProperties;
12
use ProxyManagerTestAsset\ClassWithMixedProperties;
13
use ProxyManagerTestAsset\ClassWithMixedReferenceableTypedProperties;
14
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
15
use ProxyManagerTestAsset\ClassWithPrivateProperties;
16
use ReflectionClass;
17
use ReflectionProperty;
18
use function array_map;
19
use function array_values;
20
21
/**
22
 * Tests for {@see \ProxyManager\ProxyGenerator\Util\Properties}
23
 *
24
 * @covers \ProxyManager\ProxyGenerator\Util\Properties
25
 * @group Coverage
26
 */
27
class PropertiesTest extends TestCase
28
{
29
    public function testGetPublicProperties() : void
30
    {
31
        $properties       = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
32
        $publicProperties = $properties->getPublicProperties();
33
34
        self::assertCount(3, $publicProperties);
35
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty0']);
36
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty1']);
37
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty2']);
38
    }
39
40
    public function testGetPublicPropertiesSkipsAbstractMethods() : void
41
    {
42
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractPublicMethod::class));
43
44
        self::assertEmpty($properties->getPublicProperties());
45
    }
46
47
    public function testGetProtectedProperties() : void
48
    {
49
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
50
51
        $protectedProperties = $properties->getProtectedProperties();
52
53
        self::assertCount(3, $protectedProperties);
54
55
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty0"]);
56
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty1"]);
57
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty2"]);
58
    }
59
60
    public function testOnlyNullableProperties() : void
61
    {
62
        $nullablePublicProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
63
            ->onlyNullableProperties()
64
            ->getInstanceProperties();
65
66
        self::assertCount(48, $nullablePublicProperties);
67
        self::assertSame(
68
            [
69
                'publicUnTypedProperty',
70
                'publicUnTypedPropertyWithoutDefaultValue',
71
                'publicNullableBoolProperty',
72
                'publicNullableBoolPropertyWithoutDefaultValue',
73
                'publicNullableIntProperty',
74
                'publicNullableIntPropertyWithoutDefaultValue',
75
                'publicNullableFloatProperty',
76
                'publicNullableFloatPropertyWithoutDefaultValue',
77
                'publicNullableStringProperty',
78
                'publicNullableStringPropertyWithoutDefaultValue',
79
                'publicNullableArrayProperty',
80
                'publicNullableArrayPropertyWithoutDefaultValue',
81
                'publicNullableIterableProperty',
82
                'publicNullableIterablePropertyWithoutDefaultValue',
83
                'publicNullableObjectProperty',
84
                'publicNullableClassProperty',
85
                'protectedUnTypedProperty',
86
                'protectedUnTypedPropertyWithoutDefaultValue',
87
                'protectedNullableBoolProperty',
88
                'protectedNullableBoolPropertyWithoutDefaultValue',
89
                'protectedNullableIntProperty',
90
                'protectedNullableIntPropertyWithoutDefaultValue',
91
                'protectedNullableFloatProperty',
92
                'protectedNullableFloatPropertyWithoutDefaultValue',
93
                'protectedNullableStringProperty',
94
                'protectedNullableStringPropertyWithoutDefaultValue',
95
                'protectedNullableArrayProperty',
96
                'protectedNullableArrayPropertyWithoutDefaultValue',
97
                'protectedNullableIterableProperty',
98
                'protectedNullableIterablePropertyWithoutDefaultValue',
99
                'protectedNullableObjectProperty',
100
                'protectedNullableClassProperty',
101
                'privateUnTypedProperty',
102
                'privateUnTypedPropertyWithoutDefaultValue',
103
                'privateNullableBoolProperty',
104
                'privateNullableBoolPropertyWithoutDefaultValue',
105
                'privateNullableIntProperty',
106
                'privateNullableIntPropertyWithoutDefaultValue',
107
                'privateNullableFloatProperty',
108
                'privateNullableFloatPropertyWithoutDefaultValue',
109
                'privateNullableStringProperty',
110
                'privateNullableStringPropertyWithoutDefaultValue',
111
                'privateNullableArrayProperty',
112
                'privateNullableArrayPropertyWithoutDefaultValue',
113
                'privateNullableIterableProperty',
114
                'privateNullableIterablePropertyWithoutDefaultValue',
115
                'privateNullableObjectProperty',
116
                'privateNullableClassProperty',
117
            ],
118
            array_values(array_map(static function (ReflectionProperty $property) : string {
119
                return $property->getName();
120
            }, $nullablePublicProperties))
121
        );
122
    }
123
124
    public function testOnlyPropertiesThatCanBeUnset() : void
125
    {
126
        $nonReferenceableProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
127
            ->onlyPropertiesThatCanBeUnset()
128
            ->getInstanceProperties();
129
130
        self::assertCount(42, $nonReferenceableProperties);
131
        self::assertSame(
132
            [
133
                'publicUnTypedProperty',
134
                'publicUnTypedPropertyWithoutDefaultValue',
135
                'publicBoolProperty',
136
                'publicNullableBoolProperty',
137
                'publicIntProperty',
138
                'publicNullableIntProperty',
139
                'publicFloatProperty',
140
                'publicNullableFloatProperty',
141
                'publicStringProperty',
142
                'publicNullableStringProperty',
143
                'publicArrayProperty',
144
                'publicNullableArrayProperty',
145
                'publicIterableProperty',
146
                'publicNullableIterableProperty',
147
                'protectedUnTypedProperty',
148
                'protectedUnTypedPropertyWithoutDefaultValue',
149
                'protectedBoolProperty',
150
                'protectedNullableBoolProperty',
151
                'protectedIntProperty',
152
                'protectedNullableIntProperty',
153
                'protectedFloatProperty',
154
                'protectedNullableFloatProperty',
155
                'protectedStringProperty',
156
                'protectedNullableStringProperty',
157
                'protectedArrayProperty',
158
                'protectedNullableArrayProperty',
159
                'protectedIterableProperty',
160
                'protectedNullableIterableProperty',
161
                'privateUnTypedProperty',
162
                'privateUnTypedPropertyWithoutDefaultValue',
163
                'privateBoolProperty',
164
                'privateNullableBoolProperty',
165
                'privateIntProperty',
166
                'privateNullableIntProperty',
167
                'privateFloatProperty',
168
                'privateNullableFloatProperty',
169
                'privateStringProperty',
170
                'privateNullableStringProperty',
171
                'privateArrayProperty',
172
                'privateNullableArrayProperty',
173
                'privateIterableProperty',
174
                'privateNullableIterableProperty',
175
            ],
176
            array_values(array_map(static function (ReflectionProperty $property) : string {
177
                return $property->getName();
178
            }, $nonReferenceableProperties))
179
        );
180
    }
181
182
    public function testOnlyNonReferenceableProperties() : void
183
    {
184
        self::assertTrue(
185
            Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedReferenceableTypedProperties::class))
186
                ->onlyNonReferenceableProperties()
187
                ->empty()
188
        );
189
190
        $nonReferenceableProperties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
191
            ->onlyNonReferenceableProperties()
192
            ->getInstanceProperties();
193
194
        self::assertCount(48, $nonReferenceableProperties);
195
        self::assertSame(
196
            [
197
                'publicBoolPropertyWithoutDefaultValue',
198
                'publicNullableBoolPropertyWithoutDefaultValue',
199
                'publicIntPropertyWithoutDefaultValue',
200
                'publicNullableIntPropertyWithoutDefaultValue',
201
                'publicFloatPropertyWithoutDefaultValue',
202
                'publicNullableFloatPropertyWithoutDefaultValue',
203
                'publicStringPropertyWithoutDefaultValue',
204
                'publicNullableStringPropertyWithoutDefaultValue',
205
                'publicArrayPropertyWithoutDefaultValue',
206
                'publicNullableArrayPropertyWithoutDefaultValue',
207
                'publicIterablePropertyWithoutDefaultValue',
208
                'publicNullableIterablePropertyWithoutDefaultValue',
209
                'publicObjectProperty',
210
                'publicNullableObjectProperty',
211
                'publicClassProperty',
212
                'publicNullableClassProperty',
213
                'protectedBoolPropertyWithoutDefaultValue',
214
                'protectedNullableBoolPropertyWithoutDefaultValue',
215
                'protectedIntPropertyWithoutDefaultValue',
216
                'protectedNullableIntPropertyWithoutDefaultValue',
217
                'protectedFloatPropertyWithoutDefaultValue',
218
                'protectedNullableFloatPropertyWithoutDefaultValue',
219
                'protectedStringPropertyWithoutDefaultValue',
220
                'protectedNullableStringPropertyWithoutDefaultValue',
221
                'protectedArrayPropertyWithoutDefaultValue',
222
                'protectedNullableArrayPropertyWithoutDefaultValue',
223
                'protectedIterablePropertyWithoutDefaultValue',
224
                'protectedNullableIterablePropertyWithoutDefaultValue',
225
                'protectedObjectProperty',
226
                'protectedNullableObjectProperty',
227
                'protectedClassProperty',
228
                'protectedNullableClassProperty',
229
                'privateBoolPropertyWithoutDefaultValue',
230
                'privateNullableBoolPropertyWithoutDefaultValue',
231
                'privateIntPropertyWithoutDefaultValue',
232
                'privateNullableIntPropertyWithoutDefaultValue',
233
                'privateFloatPropertyWithoutDefaultValue',
234
                'privateNullableFloatPropertyWithoutDefaultValue',
235
                'privateStringPropertyWithoutDefaultValue',
236
                'privateNullableStringPropertyWithoutDefaultValue',
237
                'privateArrayPropertyWithoutDefaultValue',
238
                'privateNullableArrayPropertyWithoutDefaultValue',
239
                'privateIterablePropertyWithoutDefaultValue',
240
                'privateNullableIterablePropertyWithoutDefaultValue',
241
                'privateObjectProperty',
242
                'privateNullableObjectProperty',
243
                'privateClassProperty',
244
                'privateNullableClassProperty',
245
            ],
246
            array_values(array_map(static function (ReflectionProperty $property) : string {
247
                return $property->getName();
248
            }, $nonReferenceableProperties))
249
        );
250
    }
251
252
    public function testGetProtectedPropertiesSkipsAbstractMethods() : void
253
    {
254
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractProtectedMethod::class));
255
256
        self::assertEmpty($properties->getProtectedProperties());
257
    }
258
259
    public function testGetPrivateProperties() : void
260
    {
261
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
262
263
        $privateProperties = $properties->getPrivateProperties();
264
265
        self::assertCount(3, $privateProperties);
266
267
        $prefix = "\0" . ClassWithMixedProperties::class . "\0";
268
269
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty0']);
270
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty1']);
271
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty2']);
272
    }
273
274
    public function testGetPrivatePropertiesFromInheritance() : void
275
    {
276
        $properties = Properties::fromReflectionClass(
277
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
278
        );
279
280
        $privateProperties = $properties->getPrivateProperties();
281
282
        self::assertCount(11, $privateProperties);
283
284
        $prefix = "\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0";
285
286
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property0']);
287
288
        $prefix = "\0" . ClassWithPrivateProperties::class . "\0";
289
290
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property0']);
291
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property1']);
292
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property2']);
293
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property3']);
294
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property4']);
295
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property5']);
296
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property6']);
297
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property7']);
298
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property8']);
299
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property9']);
300
    }
301
302
    public function testGetAccessibleMethods() : void
303
    {
304
        $properties           = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
305
        $accessibleProperties = $properties->getAccessibleProperties();
306
307
        self::assertCount(6, $accessibleProperties);
308
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty0']);
309
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty1']);
310
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty2']);
311
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty0"]);
312
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty1"]);
313
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty2"]);
314
    }
315
316
    public function testGetGroupedPrivateProperties() : void
317
    {
318
        $properties     = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
319
        $groupedPrivate = $properties->getGroupedPrivateProperties();
320
321
        self::assertCount(1, $groupedPrivate);
322
323
        $group = $groupedPrivate[ClassWithMixedProperties::class];
324
325
        self::assertCount(3, $group);
326
327
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty0']);
328
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty1']);
329
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty2']);
330
    }
331
332
    public function testGetGroupedPrivatePropertiesWithInheritedProperties() : void
333
    {
334
        $properties = Properties::fromReflectionClass(
335
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
336
        );
337
338
        $groupedPrivate = $properties->getGroupedPrivateProperties();
339
340
        self::assertCount(2, $groupedPrivate);
341
342
        $group1 = $groupedPrivate[ClassWithCollidingPrivateInheritedProperties::class];
343
        $group2 = $groupedPrivate[ClassWithPrivateProperties::class];
344
345
        self::assertCount(1, $group1);
346
        self::assertCount(10, $group2);
347
348
        self::assertInstanceOf(ReflectionProperty::class, $group1['property0']);
349
        self::assertInstanceOf(ReflectionProperty::class, $group2['property0']);
350
        self::assertInstanceOf(ReflectionProperty::class, $group2['property1']);
351
        self::assertInstanceOf(ReflectionProperty::class, $group2['property2']);
352
        self::assertInstanceOf(ReflectionProperty::class, $group2['property3']);
353
        self::assertInstanceOf(ReflectionProperty::class, $group2['property4']);
354
        self::assertInstanceOf(ReflectionProperty::class, $group2['property5']);
355
        self::assertInstanceOf(ReflectionProperty::class, $group2['property6']);
356
        self::assertInstanceOf(ReflectionProperty::class, $group2['property7']);
357
        self::assertInstanceOf(ReflectionProperty::class, $group2['property8']);
358
        self::assertInstanceOf(ReflectionProperty::class, $group2['property9']);
359
    }
360
361
    public function testGetInstanceProperties() : void
362
    {
363
        $properties = Properties::fromReflectionClass(
364
            new ReflectionClass(ClassWithMixedProperties::class)
365
        );
366
367
        self::assertCount(9, $properties->getInstanceProperties());
368
    }
369
370
    /**
371
     * @param string $propertyName with property name
372
     *
373
     * @dataProvider propertiesToSkipFixture
374
     */
375
    public function testSkipPropertiesByFiltering(string $propertyName) : void
376
    {
377
        $properties = Properties::fromReflectionClass(
378
            new ReflectionClass(ClassWithMixedProperties::class)
379
        );
380
381
        self::assertArrayHasKey($propertyName, $properties->getInstanceProperties());
382
        $filteredProperties =  $properties->filter([$propertyName]);
383
384
        self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties());
385
    }
386
387
    public function testSkipOverwritedPropertyUsingInheritance() : void
388
    {
389
        $propertyName = "\0ProxyManagerTestAsset\\ClassWithCollidingPrivateInheritedProperties\0property0";
390
391
        $properties = Properties::fromReflectionClass(
392
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
393
        );
394
395
        self::assertArrayHasKey($propertyName, $properties->getInstanceProperties());
396
        $filteredProperties =  $properties->filter([$propertyName]);
397
398
        self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties());
399
    }
400
401
    public function testPropertiesIsSkippedFromRelatedMethods() : void
402
    {
403
        $properties = Properties::fromReflectionClass(
404
            new ReflectionClass(ClassWithMixedProperties::class)
405
        );
406
407
        self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getProtectedProperties());
408
        self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getInstanceProperties());
409
        $filteredProperties =  $properties->filter(["\0*\0protectedProperty0"]);
410
411
        self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getProtectedProperties());
412
        self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getInstanceProperties());
413
    }
414
415
    /** @return string[][] */
416
    public function propertiesToSkipFixture() : array
417
    {
418
        return [
419
            ['publicProperty0'],
420
            ["\0*\0protectedProperty0"],
421
            ["\0ProxyManagerTestAsset\\ClassWithMixedProperties\0privateProperty0"],
422
        ];
423
    }
424
}
425