Completed
Pull Request — master (#83)
by Sascha-Oliver
02:05
created

EnumTest   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 327
Duplicated Lines 21.71 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 18
Bugs 9 Features 2
Metric Value
wmc 41
c 18
b 9
f 2
lcom 1
cbo 9
dl 71
loc 327
rs 8.2769

33 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetNameReturnsConstantNameOfCurrentValue() 0 5 1
A testToStringMagicMethodReturnsName() 0 5 1
B testEnumInheritance() 0 30 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 testGetEnumerators() 0 16 2
A testGetValues() 12 12 2
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 testCloneNotCallableAndThrowsLogicException() 13 13 1
A testNotSerializable() 0 7 1
A testNotUnserializable() 0 5 1
A testHas() 9 9 1
A testConstVisibility() 0 12 2
A testConstVisibilityExtended() 0 14 2
A testIsSerializableIssue() 0 12 2
A testFailureEnumWithArguments() 0 12 1

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\FailureEnumWithArguments;
12
use MabeEnumTest\TestAsset\SerializableEnum;
13
use PHPUnit_Framework_TestCase as TestCase;
14
use ReflectionClass;
15
16
/**
17
 * Unit tests for the class MabeEnum\Enum
18
 *
19
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
20
 * @copyright Copyright (c) 2015 Marc Bennewitz
21
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
22
 */
23
class EnumTest extends TestCase
24
{
25
    public function testGetNameReturnsConstantNameOfCurrentValue()
26
    {
27
        $enum = EnumBasic::get(EnumBasic::ONE);
28
        $this->assertSame('ONE', $enum->getName());
29
    }
30
31
    public function testToStringMagicMethodReturnsName()
32
    {
33
        $enum = EnumBasic::get(EnumBasic::ONE);
34
        $this->assertSame('ONE', $enum->__toString());
35
    }
36
37
    public function testEnumInheritance()
38
    {
39
        $this->assertSame(array(
40
            'ONE'           => 1,
41
            'TWO'           => 2,
42
            'THREE'         => 3,
43
            'FOUR'          => 4,
44
            'FIVE'          => 5,
45
            'SIX'           => 6,
46
            'SEVEN'         => 7,
47
            'EIGHT'         => 8,
48
            'NINE'          => 9,
49
            'ZERO'          => 0,
50
            'FLOAT'         => 0.123,
51
            'STR'           => 'str',
52
            'STR_EMPTY'     => '',
53
            'NIL'           => null,
54
            'BOOLEAN_TRUE'  => true,
55
            'BOOLEAN_FALSE' => false,
56
            'INHERITANCE'   => 'Inheritance',
57
        ), EnumInheritance::getConstants());
58
59
        $enum = EnumInheritance::get(EnumInheritance::ONE);
60
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
61
        $this->assertSame(0, $enum->getOrdinal());
62
63
        $enum = EnumInheritance::get(EnumInheritance::INHERITANCE);
64
        $this->assertSame(EnumInheritance::INHERITANCE, $enum->getValue());
65
        $this->assertSame(16, $enum->getOrdinal());
66
    }
67
68
    public function testGetWithStrictValue()
69
    {
70
        $enum = EnumBasic::get(EnumBasic::ONE);
71
        $this->assertSame(1, $enum->getValue());
72
        $this->assertSame(0, $enum->getOrdinal());
73
    }
74
75
    public function testGetWithNonStrictValueThrowsInvalidArgumentException()
76
    {
77
        $this->setExpectedException('InvalidArgumentException');
78
        EnumBasic::get((string)EnumBasic::TWO);
79
    }
80
81
    public function testGetWithInvalidValueThrowsInvalidArgumentException()
82
    {
83
        $this->setExpectedException('InvalidArgumentException');
84
        EnumBasic::get('unknown');
85
    }
86
87
    public function testGetWithInvalidTypeOfValueThrowsInvalidArgumentException()
88
    {
89
        $this->setExpectedException('InvalidArgumentException');
90
        EnumBasic::get(array());
91
    }
92
93
    public function testGetByInstance()
94
    {
95
        $enum1 = EnumBasic::get(EnumBasic::ONE);
96
        $enum2 = EnumBasic::get($enum1);
97
        $this->assertSame($enum1, $enum2);
98
    }
99
100
    public function testGetByExtendedInstanceOfKnownValue()
101
    {
102
        $enum = EnumInheritance::get(EnumInheritance::ONE);
103
104
        $this->setExpectedException('InvalidArgumentException');
105
        EnumBasic::get($enum);
106
    }
107
108
    public function testGetEnumerators()
109
    {
110
        $constants   = EnumInheritance::getConstants();
111
        $enumerators = EnumInheritance::getEnumerators();
112
        $count       = count($enumerators);
113
114
        $this->assertSame(count($constants), $count);
115
        for ($i = 0; $i < $count; ++$i) {
116
            $this->assertArrayHasKey($i, $enumerators);
117
            $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enumerators[$i]);
118
119
            $enumerator = $enumerators[$i];
120
            $this->assertArrayHasKey($enumerator->getName(), $constants);
121
            $this->assertSame($constants[$enumerator->getName()], $enumerator->getValue());
122
        }
123
    }
124
125 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...
126
    {
127
        $expectedValues = array_values(EnumInheritance::getConstants());
128
        $values         = EnumInheritance::getValues();
129
        $count          = count($values);
130
131
        $this->assertSame(count($expectedValues), $count);
132
        for ($i = 0; $i < $count; ++$i) {
133
            $this->assertArrayHasKey($i, $values);
134
            $this->assertSame($expectedValues[$i], $values[$i]);
135
        }
136
    }
137
138 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...
139
    {
140
        $expectedNames = array_keys(EnumInheritance::getConstants());
141
        $names         = EnumInheritance::getNames();
142
        $count         = count($names);
143
144
        $this->assertSame(count($expectedNames), $count);
145
        for ($i = 0; $i < $count; ++$i) {
146
            $this->assertArrayHasKey($i, $names);
147
            $this->assertSame($expectedNames[$i], $names[$i]);
148
        }
149
    }
150
151 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...
152
    {
153
        $constants = EnumInheritance::getConstants();
154
        $ordinals  = EnumInheritance::getOrdinals();
155
        $count     = count($ordinals);
156
157
        $this->assertSame(count($constants), $count);
158
        for ($i = 0; $i < $count; ++$i) {
159
            $this->assertArrayHasKey($i, $ordinals);
160
            $this->assertSame($i, $ordinals[$i]);
161
        }
162
    }
163
164
    public function testGetAllValues()
165
    {
166
        $constants = EnumBasic::getConstants();
167
        foreach ($constants as $name => $value) {
168
            $enum = EnumBasic::get($value);
169
            $this->assertSame($value, $enum->getValue());
170
            $this->assertSame($name, $enum->getName());
171
        }
172
    }
173
174 View Code Duplication
    public function testIsBasic()
175
    {
176
        $enum = EnumBasic::ONE();
177
178
        // by value
179
        $this->assertTrue($enum->is(EnumBasic::ONE));   // same
180
        $this->assertFalse($enum->is('1'));             // wrong value by strict comparison
181
182
        // by instance
183
        $this->assertTrue($enum->is(EnumBasic::ONE()));        // same
184
        $this->assertFalse($enum->is(EnumBasic::TWO()));       // different enumerators
185
        $this->assertFalse($enum->is(EnumInheritance::ONE())); // different enumeration type
186
    }
187
188
    public function testCallingGetOrdinalTwoTimesWillResultTheSameValue()
189
    {
190
        $enum = EnumBasic::get(EnumBasic::TWO);
191
        $this->assertSame(1, $enum->getOrdinal());
192
        $this->assertSame(1, $enum->getOrdinal());
193
    }
194
195
    public function testInstantiateUsingOrdinalNumber()
196
    {
197
        $enum = EnumInheritance::byOrdinal(16);
198
        $this->assertSame(16, $enum->getOrdinal());
199
        $this->assertSame('INHERITANCE', $enum->getName());
200
    }
201
202
    public function testInstantiateUsingInvalidOrdinalNumberThrowsInvalidArgumentException()
203
    {
204
        $this->setExpectedException('InvalidArgumentException');
205
        EnumInheritance::byOrdinal(17);
206
    }
207
208
    public function testInstantiateByName()
209
    {
210
        $enum = EnumInheritance::byName('ONE');
211
        $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enum);
212
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
213
    }
214
215
    public function testInstantiateByUnknownNameThrowsInvalidArgumentException()
216
    {
217
        $this->setExpectedException('InvalidArgumentException');
218
        EnumInheritance::byName('UNKNOWN');
219
    }
220
221
    public function testInstantiateUsingMagicMethod()
222
    {
223
        $enum = EnumInheritance::ONE();
224
        $this->assertInstanceOf('MabeEnumTest\TestAsset\EnumInheritance', $enum);
225
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
226
    }
227
228
    public function testAmbiguousConstantsThrowsLogicException()
229
    {
230
        $this->setExpectedException('LogicException');
231
        EnumAmbiguous::get('unknown');
232
    }
233
234
    public function testExtendedAmbiguousCanstantsThrowsLogicException()
235
    {
236
        $this->setExpectedException('LogicException');
237
        EnumExtendedAmbiguous::get('unknown');
238
    }
239
240
    public function testSingleton()
241
    {
242
        $enum1 = EnumBasic::get(EnumBasic::ONE);
243
        $enum2 = EnumBasic::ONE();
244
        $this->assertSame($enum1, $enum2);
245
    }
246
247
    public function testClear()
248
    {
249
        $enum1 = EnumBasic::ONE();
250
        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...
251
        $enum2 = EnumBasic::ONE();
252
        $enum3 = EnumBasic::ONE();
253
        
254
        $this->assertNotSame($enum1, $enum2);
255
        $this->assertSame($enum2, $enum3);
256
    }
257
258 View Code Duplication
    public function testCloneNotCallableAndThrowsLogicException()
259
    {
260
        $enum = EnumBasic::ONE();
261
262
        $reflectionClass  = new ReflectionClass($enum);
263
        $reflectionMethod = $reflectionClass->getMethod('__clone');
264
        $this->assertTrue($reflectionMethod->isPrivate(), 'The method __clone must be private');
265
        $this->assertTrue($reflectionMethod->isFinal(), 'The method __clone must be final');
266
267
        $reflectionMethod->setAccessible(true);
268
        $this->setExpectedException('LogicException');
269
        $reflectionMethod->invoke($enum);
270
    }
271
272
    public function testNotSerializable()
273
    {
274
        $enum = EnumBasic::ONE();
275
276
        $this->setExpectedException('LogicException');
277
        serialize($enum);
278
    }
279
280
    public function testNotUnserializable()
281
    {
282
        $this->setExpectedException('LogicException');
283
        unserialize("O:32:\"MabeEnumTest\TestAsset\EnumBasic\":0:{}");
284
    }
285
286 View Code Duplication
    public function testHas()
287
    {
288
        $enum = EnumBasic::ONE();
289
290
        $this->assertFalse($enum->has('invalid'));
291
        $this->assertFalse($enum->has(EnumInheritance::ONE()));
292
        $this->assertTrue($enum->has(EnumBasic::ONE()));
293
        $this->assertTrue($enum->has(EnumBasic::ONE));
294
    }
295
    
296
    public function testConstVisibility()
297
    {
298
        if (PHP_VERSION_ID < 70100) {
299
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
300
        }
301
302
        $constants = ConstVisibilityEnum::getConstants();
303
        $this->assertSame(array(
304
            'IPUB' => ConstVisibilityEnum::IPUB,
305
            'PUB'  => ConstVisibilityEnum::PUB,
306
        ), $constants);
307
    }
308
    
309
    public function testConstVisibilityExtended()
310
    {
311
        if (PHP_VERSION_ID < 70100) {
312
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
313
        }
314
315
        $constants = ConstVisibilityEnumExtended::getConstants();
316
        $this->assertSame(array(
317
            'IPUB'  => ConstVisibilityEnumExtended::IPUB,
318
            'PUB'   => ConstVisibilityEnumExtended::PUB,
319
            'IPUB2' => ConstVisibilityEnumExtended::IPUB2,
320
            'PUB2'  => ConstVisibilityEnumExtended::PUB2,
321
        ), $constants);
322
    }
323
324
    public function testIsSerializableIssue()
325
    {
326
        if (PHP_VERSION_ID < 50400) {
327
            $this->markTestSkipped('This test is for PHP-5.4 and upper only');
328
        }
329
330
        $enum1 = SerializableEnum::INT();
331
        $enum2 = unserialize(serialize($enum1));
332
333
        $this->assertFalse($enum1 === $enum2, 'Wrong test implementation');
334
        $this->assertTrue($enum1->is($enum2), 'Two different instances of exact the same enumerator should be equal');
335
    }
336
337
    public function testFailureEnumWithArguments()
338
    {
339
        $failure1 = FailureEnumWithArguments::VALIDATION_ERROR('foo');
340
        $this->assertInstanceOf('MabeEnumTest\TestAsset\FailureEnumWithArguments', $failure1);
341
        $this->assertEquals('foo', $failure1->message());
342
343
        $failure2 = FailureEnumWithArguments::DB_ERROR('bar');
344
        $this->assertInstanceOf('MabeEnumTest\TestAsset\FailureEnumWithArguments', $failure2);
345
        $this->assertEquals('bar', $failure2->message());
346
347
        $this->assertNotSame($failure1, $failure2);
348
    }
349
}
350