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:
| 1 | <?php |
||
| 17 | final class SimpleCacheAdapterTest extends \PHPUnit_Framework_TestCase |
||
| 18 | { |
||
| 19 | public function invalidTTLs() : array |
||
| 20 | { |
||
| 21 | return [ |
||
| 22 | [''], |
||
| 23 | [true], |
||
| 24 | [false], |
||
| 25 | ['abc'], |
||
| 26 | [2.5], |
||
| 27 | [' 1'], // can be casted to a int |
||
| 28 | ['12foo'], // can be casted to a int |
||
| 29 | ['025'], // can be interpreted as hex |
||
| 30 | [new \stdClass()], |
||
| 31 | [['array']], |
||
| 32 | ]; |
||
| 33 | } |
||
| 34 | |||
| 35 | public function validKeys() |
||
| 36 | { |
||
| 37 | return [ |
||
| 38 | ['AbC19_.'], |
||
| 39 | ['1234567890123456789012345678901234567890123456789012345678901234'], |
||
| 40 | ]; |
||
| 41 | } |
||
| 42 | |||
| 43 | public function invalidKeys() |
||
| 44 | { |
||
| 45 | return [ |
||
| 46 | [''], |
||
| 47 | [true], |
||
| 48 | [false], |
||
| 49 | [null], |
||
| 50 | [2], |
||
| 51 | [2.5], |
||
| 52 | ['{str'], |
||
| 53 | ['rand{'], |
||
| 54 | ['rand{str'], |
||
| 55 | ['rand}str'], |
||
| 56 | ['rand(str'], |
||
| 57 | ['rand)str'], |
||
| 58 | ['rand/str'], |
||
| 59 | ['rand\\str'], |
||
| 60 | ['rand@str'], |
||
| 61 | ['rand:str'], |
||
| 62 | [new \stdClass()], |
||
| 63 | [['array']], |
||
| 64 | ]; |
||
| 65 | } |
||
| 66 | |||
| 67 | public function testConstructorThrowsExceptionWhenNotMultiOperationCacheIsUsed() |
||
| 68 | { |
||
| 69 | /** @var NotMultiOperationCache|\PHPUnit_Framework_MockObject_MockObject $doctrineCache */ |
||
| 70 | $doctrineCache = $this->createMock(NotMultiOperationCache::class); |
||
| 71 | |||
| 72 | $this->expectException(CacheException::class); |
||
| 73 | new SimpleCacheAdapter($doctrineCache); |
||
|
|
|||
| 74 | } |
||
| 75 | |||
| 76 | public function testConstructorThrowsExceptionWhenNotClearableCacheIsUsed() |
||
| 77 | { |
||
| 78 | /** @var NotClearableCache|\PHPUnit_Framework_MockObject_MockObject $doctrineCache */ |
||
| 79 | $doctrineCache = $this->createMock(NotClearableCache::class); |
||
| 80 | |||
| 81 | $this->expectException(CacheException::class); |
||
| 82 | new SimpleCacheAdapter($doctrineCache); |
||
| 83 | } |
||
| 84 | |||
| 85 | View Code Duplication | public function testGetProxiesToDoctrineFetch() |
|
| 86 | { |
||
| 87 | $key = uniqid('key', true); |
||
| 88 | $value = uniqid('value', true); |
||
| 89 | |||
| 90 | /** @var FullyImplementedCache|\PHPUnit_Framework_MockObject_MockObject $doctrineCache */ |
||
| 91 | $doctrineCache = $this->createMock(FullyImplementedCache::class); |
||
| 92 | $doctrineCache->expects(self::once())->method('fetch')->with($key)->willReturn($value); |
||
| 93 | |||
| 94 | $psrCache = new SimpleCacheAdapter($doctrineCache); |
||
| 95 | self::assertSame($value, $psrCache->get($key)); |
||
| 96 | } |
||
| 97 | |||
| 98 | public function testGetWithNotExistingKey() |
||
| 99 | { |
||
| 100 | $key = uniqid('key', true); |
||
| 101 | $value = uniqid('value', true); |
||
| 102 | |||
| 103 | $psrCache = new SimpleCacheAdapter(new ArrayCache()); |
||
| 104 | $psrCache->set($key, $value); |
||
| 105 | |||
| 106 | $default = uniqid('default', true); |
||
| 107 | self::assertSame($value, $psrCache->get($key, $default)); |
||
| 108 | |||
| 109 | $anotherKey = uniqid('key', true); |
||
| 110 | self::assertSame($default, $psrCache->get($anotherKey, $default)); |
||
| 111 | } |
||
| 112 | |||
| 113 | View Code Duplication | public function testGetWithFalseValueStoredInCache() |
|
| 114 | { |
||
| 115 | $key = uniqid('key', true); |
||
| 116 | |||
| 117 | $psrCache = new SimpleCacheAdapter(new ArrayCache()); |
||
| 118 | $psrCache->set($key, false); |
||
| 119 | |||
| 120 | self::assertFalse($psrCache->get($key, uniqid('default', true))); |
||
| 121 | } |
||
| 122 | |||
| 123 | public function testSetProxiesToDoctrineSave() |
||
| 136 | |||
| 137 | public function testSetWithDateIntervalTTL() |
||
| 149 | |||
| 150 | public function testSetWithNonPositiveTTL() |
||
| 164 | |||
| 165 | /** |
||
| 166 | * @param mixed $ttl |
||
| 167 | * @dataProvider invalidTTLs |
||
| 168 | */ |
||
| 169 | View Code Duplication | public function testSetWithInvalidTTL($ttl) |
|
| 170 | { |
||
| 171 | $key = uniqid('key', true); |
||
| 172 | $value = uniqid('value', true); |
||
| 173 | |||
| 174 | $psrCache = new SimpleCacheAdapter(new ArrayCache()); |
||
| 175 | |||
| 176 | $this->expectException(InvalidArgumentException::class); |
||
| 177 | $psrCache->set($key, $value, $ttl); |
||
| 178 | } |
||
| 179 | |||
| 180 | View Code Duplication | public function testDeleteProxiesToDoctrineDelete() |
|
| 191 | |||
| 192 | public function testClearProxiesToDeleteAll() |
||
| 201 | |||
| 202 | public function testGetMultipleProxiesToFetchMultiple() |
||
| 217 | |||
| 218 | public function testGetMultipleWithPartialKeys() |
||
| 236 | |||
| 237 | /** |
||
| 238 | * @param mixed $key |
||
| 239 | * @dataProvider invalidKeys |
||
| 240 | */ |
||
| 241 | public function testGetMultipleThrowsExceptionWithInvalidKeys($key) |
||
| 248 | |||
| 249 | /** |
||
| 250 | * @param mixed $key |
||
| 251 | * @dataProvider validKeys |
||
| 252 | */ |
||
| 253 | View Code Duplication | public function testGetMultipleAcceptsTraversable($key) |
|
| 266 | |||
| 267 | public function testGetMultipleAcceptsGenerator() |
||
| 268 | { |
||
| 269 | $values = [ |
||
| 270 | uniqid('key0', true) => uniqid('value0', true), |
||
| 271 | uniqid('key1', true) => uniqid('value1', true), |
||
| 272 | ]; |
||
| 273 | |||
| 274 | $generator = function () use ($values) { |
||
| 275 | /** @noinspection ForeachOnArrayComponentsInspection */ |
||
| 286 | |||
| 287 | View Code Duplication | public function testGetMultipleThrowsExceptionWhenNotArrayOrTraversable() |
|
| 294 | |||
| 295 | public function testSetMultipleProxiesToSaveMultiple() |
||
| 309 | |||
| 310 | public function testSetMultipleWithDateIntervalTTL() |
||
| 325 | |||
| 326 | public function testSetMultipleWithNonPositiveTTL() |
||
| 343 | |||
| 344 | /** |
||
| 345 | * @param mixed $ttl |
||
| 346 | * @dataProvider invalidTTLs |
||
| 347 | */ |
||
| 348 | public function testSetMultipleWithInvalidTTL($ttl) |
||
| 360 | |||
| 361 | View Code Duplication | public function testSetMultipleThrowsExceptionWhenNotArrayOrTraversable() |
|
| 368 | |||
| 369 | public function testSetMultipleAcceptsGenerator() |
||
| 390 | |||
| 391 | View Code Duplication | public function testDeleteMultipleReturnsTrueWhenAllDeletesSucceed() |
|
| 405 | |||
| 406 | View Code Duplication | public function testDeleteMultipleReturnsFalseWhenOneDeleteFails() |
|
| 420 | |||
| 421 | View Code Duplication | public function testHasProxiesToDoctrineContains() |
|
| 432 | } |
||
| 433 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.