Completed
Pull Request — master (#84)
by
unknown
03:42
created

EnumTest   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 314
Duplicated Lines 18.47 %

Coupling/Cohesion

Components 2
Dependencies 8

Importance

Changes 18
Bugs 9 Features 2
Metric Value
wmc 40
lcom 2
cbo 8
dl 58
loc 314
rs 8.2608
c 18
b 9
f 2

32 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetNameReturnsConstantNameOfCurrentValue() 0 5 1
A testToStringMagicMethodReturnsName() 0 5 1
A testGetWithStrictValue() 0 6 1
A testGetWithNonStrictValueThrowsInvalidArgumentException() 0 5 1
A testGetWithInvalidValueThrowsInvalidArgumentException() 0 5 1
A testGetWithInvalidTypeOfValueThrowsInvalidArgumentException() 0 5 1
A testGetByInstance() 0 6 1
A testGetByExtendedInstanceOfKnownValue() 0 7 1
A testGetNames() 12 12 2
A testGetOrdinals() 12 12 2
A testGetAllValues() 0 9 2
A testIsBasic() 13 13 1
A testCallingGetOrdinalTwoTimesWillResultTheSameValue() 0 6 1
A testInstantiateUsingOrdinalNumber() 0 6 1
A testInstantiateUsingInvalidOrdinalNumberThrowsInvalidArgumentException() 0 5 1
A testInstantiateByName() 0 6 1
A testInstantiateByUnknownNameThrowsInvalidArgumentException() 0 5 1
A testInstantiateUsingMagicMethod() 0 6 1
A testAmbiguousConstantsThrowsLogicException() 0 5 1
A testExtendedAmbiguousCanstantsThrowsLogicException() 0 5 1
A testSingleton() 0 6 1
A testClear() 0 10 1
A testNotSerializable() 0 7 1
A testNotUnserializable() 0 5 1
A testIsSerializableIssue() 0 12 2
A testHas() 9 9 1
B testEnumInheritance() 0 30 1
A testGetEnumerators() 0 16 2
A testGetValues() 12 12 2
A testClone() 0 13 1
A testConstVisibility() 0 12 2
A testConstVisibilityExtended() 0 14 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EnumTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EnumTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace MabeEnumTest;
4
5
use MabeEnumTest\TestAsset\EnumBasic;
6
use MabeEnumTest\TestAsset\EnumInheritance;
7
use MabeEnumTest\TestAsset\EnumAmbiguous;
8
use MabeEnumTest\TestAsset\EnumExtendedAmbiguous;
9
use MabeEnumTest\TestAsset\ConstVisibilityEnum;
10
use MabeEnumTest\TestAsset\ConstVisibilityEnumExtended;
11
use MabeEnumTest\TestAsset\SerializableEnum;
12
use PHPUnit_Framework_TestCase as TestCase;
13
use ReflectionClass;
14
15
/**
16
 * Unit tests for the class MabeEnum\Enum
17
 *
18
 * @link      http://github.com/marc-mabe/php-enum for the canonical source repository
19
 * @copyright Copyright (c) 2015 Marc Bennewitz
20
 * @license   http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
21
 */
22
class EnumTest extends TestCase
23
{
24
    public function testGetNameReturnsConstantNameOfCurrentValue()
25
    {
26
        $enum = EnumBasic::get(EnumBasic::ONE);
27
        $this->assertSame('ONE', $enum->getName());
28
    }
29
30
    public function testToStringMagicMethodReturnsName()
31
    {
32
        $enum = EnumBasic::get(EnumBasic::ONE);
33
        $this->assertSame('ONE', $enum->__toString());
34
    }
35
36
    public function testEnumInheritance()
37
    {
38
        $this->assertSame([
39
            'ONE'           => 1,
40
            'TWO'           => 2,
41
            'THREE'         => 3,
42
            'FOUR'          => 4,
43
            'FIVE'          => 5,
44
            'SIX'           => 6,
45
            'SEVEN'         => 7,
46
            'EIGHT'         => 8,
47
            'NINE'          => 9,
48
            'ZERO'          => 0,
49
            'FLOAT'         => 0.123,
50
            'STR'           => 'str',
51
            'STR_EMPTY'     => '',
52
            'NIL'           => null,
53
            'BOOLEAN_TRUE'  => true,
54
            'BOOLEAN_FALSE' => false,
55
            'INHERITANCE'   => 'Inheritance',
56
        ], EnumInheritance::getConstants());
57
58
        $enum = EnumInheritance::get(EnumInheritance::ONE);
59
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
60
        $this->assertSame(0, $enum->getOrdinal());
61
62
        $enum = EnumInheritance::get(EnumInheritance::INHERITANCE);
63
        $this->assertSame(EnumInheritance::INHERITANCE, $enum->getValue());
64
        $this->assertSame(16, $enum->getOrdinal());
65
    }
66
67
    public function testGetWithStrictValue()
68
    {
69
        $enum = EnumBasic::get(EnumBasic::ONE);
70
        $this->assertSame(1, $enum->getValue());
71
        $this->assertSame(0, $enum->getOrdinal());
72
    }
73
74
    public function testGetWithNonStrictValueThrowsInvalidArgumentException()
75
    {
76
        $this->setExpectedException('InvalidArgumentException');
77
        EnumBasic::get((string)EnumBasic::TWO);
78
    }
79
80
    public function testGetWithInvalidValueThrowsInvalidArgumentException()
81
    {
82
        $this->setExpectedException('InvalidArgumentException');
83
        EnumBasic::get('unknown');
84
    }
85
86
    public function testGetWithInvalidTypeOfValueThrowsInvalidArgumentException()
87
    {
88
        $this->setExpectedException('InvalidArgumentException');
89
        EnumBasic::get([]);
90
    }
91
92
    public function testGetByInstance()
93
    {
94
        $enum1 = EnumBasic::get(EnumBasic::ONE);
95
        $enum2 = EnumBasic::get($enum1);
96
        $this->assertSame($enum1, $enum2);
97
    }
98
99
    public function testGetByExtendedInstanceOfKnownValue()
100
    {
101
        $enum = EnumInheritance::get(EnumInheritance::ONE);
102
103
        $this->setExpectedException('InvalidArgumentException');
104
        EnumBasic::get($enum);
105
    }
106
107
    public function testGetEnumerators()
108
    {
109
        $constants = EnumInheritance::getConstants();
110
        $enumerators = EnumInheritance::getEnumerators();
111
        $count = count($enumerators);
112
113
        $this->assertSame(count($constants), $count);
114
        for ($i = 0; $i < $count; ++$i) {
115
            $this->assertArrayHasKey($i, $enumerators);
116
            $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enumerators[ $i ]);
117
118
            $enumerator = $enumerators[ $i ];
119
            $this->assertArrayHasKey($enumerator->getName(), $constants);
120
            $this->assertSame($constants[ $enumerator->getName() ], $enumerator->getValue());
121
        }
122
    }
123
124 View Code Duplication
    public function testGetValues()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
    {
126
        $expectedValues = array_values(EnumInheritance::getConstants());
127
        $values = EnumInheritance::getValues();
128
        $count = count($values);
129
130
        $this->assertSame(count($expectedValues), $count);
131
        for ($i = 0; $i < $count; ++$i) {
132
            $this->assertArrayHasKey($i, $values);
133
            $this->assertSame($expectedValues[ $i ], $values[ $i ]);
134
        }
135
    }
136
137 View Code Duplication
    public function testGetNames()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
138
    {
139
        $expectedNames = array_keys(EnumInheritance::getConstants());
140
        $names = EnumInheritance::getNames();
141
        $count = count($names);
142
143
        $this->assertSame(count($expectedNames), $count);
144
        for ($i = 0; $i < $count; ++$i) {
145
            $this->assertArrayHasKey($i, $names);
146
            $this->assertSame($expectedNames[ $i ], $names[ $i ]);
147
        }
148
    }
149
150 View Code Duplication
    public function testGetOrdinals()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
    {
152
        $constants = EnumInheritance::getConstants();
153
        $ordinals = EnumInheritance::getOrdinals();
154
        $count = count($ordinals);
155
156
        $this->assertSame(count($constants), $count);
157
        for ($i = 0; $i < $count; ++$i) {
158
            $this->assertArrayHasKey($i, $ordinals);
159
            $this->assertSame($i, $ordinals[ $i ]);
160
        }
161
    }
162
163
    public function testGetAllValues()
164
    {
165
        $constants = EnumBasic::getConstants();
166
        foreach ($constants as $name => $value) {
167
            $enum = EnumBasic::get($value);
168
            $this->assertSame($value, $enum->getValue());
169
            $this->assertSame($name, $enum->getName());
170
        }
171
    }
172
173 View Code Duplication
    public function testIsBasic()
174
    {
175
        $enum = EnumBasic::ONE();
176
177
        // by value
178
        $this->assertTrue($enum->is(EnumBasic::ONE));   // same
179
        $this->assertFalse($enum->is('1'));             // wrong value by strict comparison
180
181
        // by instance
182
        $this->assertTrue($enum->is(EnumBasic::ONE()));        // same
183
        $this->assertFalse($enum->is(EnumBasic::TWO()));       // different enumerators
184
        $this->assertFalse($enum->is(EnumInheritance::ONE())); // different enumeration type
185
    }
186
187
    public function testCallingGetOrdinalTwoTimesWillResultTheSameValue()
188
    {
189
        $enum = EnumBasic::get(EnumBasic::TWO);
190
        $this->assertSame(1, $enum->getOrdinal());
191
        $this->assertSame(1, $enum->getOrdinal());
192
    }
193
194
    public function testInstantiateUsingOrdinalNumber()
195
    {
196
        $enum = EnumInheritance::byOrdinal(16);
197
        $this->assertSame(16, $enum->getOrdinal());
198
        $this->assertSame('INHERITANCE', $enum->getName());
199
    }
200
201
    public function testInstantiateUsingInvalidOrdinalNumberThrowsInvalidArgumentException()
202
    {
203
        $this->setExpectedException('InvalidArgumentException');
204
        EnumInheritance::byOrdinal(17);
205
    }
206
207
    public function testInstantiateByName()
208
    {
209
        $enum = EnumInheritance::byName('ONE');
210
        $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enum);
211
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
212
    }
213
214
    public function testInstantiateByUnknownNameThrowsInvalidArgumentException()
215
    {
216
        $this->setExpectedException('InvalidArgumentException');
217
        EnumInheritance::byName('UNKNOWN');
218
    }
219
220
    public function testInstantiateUsingMagicMethod()
221
    {
222
        $enum = EnumInheritance::ONE();
223
        $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enum);
224
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
225
    }
226
227
    public function testAmbiguousConstantsThrowsLogicException()
228
    {
229
        $this->setExpectedException('LogicException');
230
        EnumAmbiguous::get('unknown');
231
    }
232
233
    public function testExtendedAmbiguousCanstantsThrowsLogicException()
234
    {
235
        $this->setExpectedException('LogicException');
236
        EnumExtendedAmbiguous::get('unknown');
237
    }
238
239
    public function testSingleton()
240
    {
241
        $enum1 = EnumBasic::get(EnumBasic::ONE);
242
        $enum2 = EnumBasic::ONE();
243
        $this->assertSame($enum1, $enum2);
244
    }
245
246
    public function testClear()
247
    {
248
        $enum1 = EnumBasic::ONE();
249
        EnumBasic::clear();
0 ignored issues
show
Deprecated Code introduced by
The method MabeEnum\Enum::clear() has been deprecated.

This method has been deprecated.

Loading history...
250
        $enum2 = EnumBasic::ONE();
251
        $enum3 = EnumBasic::ONE();
252
253
        $this->assertNotSame($enum1, $enum2);
254
        $this->assertSame($enum2, $enum3);
255
    }
256
257
    public function testClone()
258
    {
259
        $enum = EnumBasic::ONE();
260
261
        $reflectionClass = new ReflectionClass($enum);
262
        $reflectionMethod = $reflectionClass->getMethod('__clone');
263
        $this->assertTrue($reflectionMethod->isPublic(), 'The method __clone must be private');
264
        $this->assertTrue($reflectionMethod->isFinal(), 'The method __clone must be final');
265
266
        $reflectionMethod->setAccessible(true);
267
        $enumClone = $reflectionMethod->invoke($enum);
268
        $this->assertSame($enum, $enumClone);
269
    }
270
271
    public function testNotSerializable()
272
    {
273
        $enum = EnumBasic::ONE();
274
275
        $this->setExpectedException('LogicException');
276
        serialize($enum);
277
    }
278
279
    public function testNotUnserializable()
280
    {
281
        $this->setExpectedException('LogicException');
282
        unserialize("O:32:\"MabeEnumTest\TestAsset\EnumBasic\":0:{}");
283
    }
284
285 View Code Duplication
    public function testHas()
286
    {
287
        $enum = EnumBasic::ONE();
288
289
        $this->assertFalse($enum->has('invalid'));
290
        $this->assertFalse($enum->has(EnumInheritance::ONE()));
291
        $this->assertTrue($enum->has(EnumBasic::ONE()));
292
        $this->assertTrue($enum->has(EnumBasic::ONE));
293
    }
294
295
    public function testConstVisibility()
296
    {
297
        if (PHP_VERSION_ID < 70100) {
298
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
299
        }
300
301
        $constants = ConstVisibilityEnum::getConstants();
302
        $this->assertSame([
303
            'IPUB' => ConstVisibilityEnum::IPUB,
304
            'PUB'  => ConstVisibilityEnum::PUB,
305
        ], $constants);
306
    }
307
308
    public function testConstVisibilityExtended()
309
    {
310
        if (PHP_VERSION_ID < 70100) {
311
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
312
        }
313
314
        $constants = ConstVisibilityEnumExtended::getConstants();
315
        $this->assertSame([
316
            'IPUB'  => ConstVisibilityEnumExtended::IPUB,
317
            'PUB'   => ConstVisibilityEnumExtended::PUB,
318
            'IPUB2' => ConstVisibilityEnumExtended::IPUB2,
319
            'PUB2'  => ConstVisibilityEnumExtended::PUB2,
320
        ], $constants);
321
    }
322
323
    public function testIsSerializableIssue()
324
    {
325
        if (PHP_VERSION_ID < 50400) {
326
            $this->markTestSkipped('This test is for PHP-5.4 and upper only');
327
        }
328
329
        $enum1 = SerializableEnum::INT();
330
        $enum2 = unserialize(serialize($enum1));
331
332
        $this->assertFalse($enum1 === $enum2, 'Wrong test implementation');
333
        $this->assertTrue($enum1->is($enum2), 'Two different instances of exact the same enumerator should be equal');
334
    }
335
}
336