1
|
|
|
<?php |
2
|
|
|
namespace Chadicus\Marvel\Api\Cache; |
3
|
|
|
|
4
|
|
|
use Chadicus\Marvel\Api\Request; |
5
|
|
|
use Chadicus\Marvel\Api\Response; |
6
|
|
|
use MongoDB\Collection; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Defines unit tests for the MongoCache class. |
10
|
|
|
* |
11
|
|
|
* @coversDefaultClass \Chadicus\Marvel\Api\Cache\MongoCache |
12
|
|
|
*/ |
13
|
|
|
final class MongoCacheTest extends \PHPUnit_Framework_TestCase |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* set up each test. |
17
|
|
|
* |
18
|
|
|
* @return void |
19
|
|
|
*/ |
20
|
|
|
public function setUp() |
21
|
|
|
{ |
22
|
|
|
\Chadicus\FunctionRegistry::reset(__NAMESPACE__, ['date', 'Core']); |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Tear down each test. |
27
|
|
|
* |
28
|
|
|
* @return void |
29
|
|
|
*/ |
30
|
|
|
public function tearDown() |
31
|
|
|
{ |
32
|
|
|
\Chadicus\FunctionRegistry::reset(__NAMESPACE__, ['date', 'Core']); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Verify cache is removed when expired. |
37
|
|
|
* |
38
|
|
|
* @test |
39
|
|
|
* @covers ::set |
40
|
|
|
* @expectedException \InvalidArgumentException |
41
|
|
|
* @expectedExceptionMessage TTL value must be an integer >= 1 and <= 86400 |
42
|
|
|
* |
43
|
|
|
* @return void |
44
|
|
|
*/ |
45
|
|
View Code Duplication |
public function setTtlIsLessThanOne() |
|
|
|
|
46
|
|
|
{ |
47
|
|
|
(new MongoCache(self::getMongoCollection()))->set( |
48
|
|
|
new Request('not under test', 'not under test', [], []), |
49
|
|
|
new Response(200, [], []), |
50
|
|
|
-1 |
51
|
|
|
); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Verify cache is removed when expired. |
56
|
|
|
* |
57
|
|
|
* @test |
58
|
|
|
* @covers ::set |
59
|
|
|
* @expectedException \InvalidArgumentException |
60
|
|
|
* @expectedExceptionMessage TTL value must be an integer >= 1 and <= 86400 |
61
|
|
|
* |
62
|
|
|
* @return void |
63
|
|
|
*/ |
64
|
|
View Code Duplication |
public function setTtlIsGreaterThanMax() |
|
|
|
|
65
|
|
|
{ |
66
|
|
|
(new MongoCache(self::getMongoCollection()))->set( |
67
|
|
|
new Request('not under test', 'not under test', [], []), |
68
|
|
|
new Response(200, [], []), |
69
|
|
|
CacheInterface::MAX_TTL + 1 |
70
|
|
|
); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Verify cache is removed when expired. |
75
|
|
|
* |
76
|
|
|
* @test |
77
|
|
|
* @covers ::get |
78
|
|
|
* |
79
|
|
|
* @return void |
80
|
|
|
*/ |
81
|
|
|
public function getNotFound() |
82
|
|
|
{ |
83
|
|
|
$cache = new MongoCache(self::getMongoCollection()); |
84
|
|
|
$request = new Request('not under test', 'not under test', [], []); |
85
|
|
|
$this->assertNull($cache->get($request)); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Verify cache is removed when expired. |
90
|
|
|
* |
91
|
|
|
* @test |
92
|
|
|
* @covers ::__construct |
93
|
|
|
* @covers ::set |
94
|
|
|
* @covers ::get |
95
|
|
|
* |
96
|
|
|
* @return void |
97
|
|
|
*/ |
98
|
|
|
public function getExpired() |
99
|
|
|
{ |
100
|
|
|
\Chadicus\FunctionRegistry::set( |
101
|
|
|
__NAMESPACE__, |
102
|
|
|
'time', |
103
|
|
|
function () { |
104
|
|
|
return strtotime('-1 year'); |
105
|
|
|
} |
106
|
|
|
); |
107
|
|
|
|
108
|
|
|
$collection = self::getMongoCollection(); |
109
|
|
|
$cache = new MongoCache($collection); |
110
|
|
|
$request = new Request('not under test', 'not under test', [], []); |
111
|
|
|
$cache->set($request, new Response(200, [], [])); |
112
|
|
|
$this->assertNotNull($cache->get($request)); |
113
|
|
|
$endTime = \time() + 60; |
114
|
|
|
while (\time() <= $endTime) { |
115
|
|
|
if ($collection->count() === 0) { |
116
|
|
|
break; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
\usleep(500000); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if ($collection->count() !== 0) { |
123
|
|
|
$this->markTestSkipped('Mongo index took too long'); |
124
|
|
|
return; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
$this->assertNull($cache->get($request)); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Verify construct throws with invalid parameters. |
132
|
|
|
* |
133
|
|
|
* @param mixed $collection The collection containing the cached data. |
134
|
|
|
* @param mixed $defaultTimeToLive The default time to live in seconds. |
135
|
|
|
* |
136
|
|
|
* @test |
137
|
|
|
* @covers ::__construct |
138
|
|
|
* @dataProvider badConstructorData |
139
|
|
|
* @expectedException \InvalidArgumentException |
140
|
|
|
* @expectedExceptionMessage TTL value must be an integer >= 1 and <= 86400 |
141
|
|
|
* |
142
|
|
|
* @return void |
143
|
|
|
*/ |
144
|
|
|
public function constructWithBadData($collection, $defaultTimeToLive) |
145
|
|
|
{ |
146
|
|
|
new MongoCache($collection, $defaultTimeToLive); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Data provider for constructWithBadData. |
151
|
|
|
* |
152
|
|
|
* @return array |
153
|
|
|
*/ |
154
|
|
|
public function badConstructorData() |
155
|
|
|
{ |
156
|
|
|
return [ |
157
|
|
|
'defaultTimeToLive is not an integer' => [self::getMongoCollection(), 'a string'], |
158
|
|
|
'defaultTimeToLive is less than 1' => [self::getMongoCollection(), -1], |
159
|
|
|
'defaultTimeToLive is greater than CacheInterface::MAX_TTL' => [ |
160
|
|
|
self::getMongoCollection(), |
161
|
|
|
CacheInterface::MAX_TTL + 1 |
162
|
|
|
], |
163
|
|
|
'defaultTimeToLive is null' => [self::getMongoCollection(), null], |
164
|
|
|
]; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Helper method to get a mongo collection for testing. |
169
|
|
|
* |
170
|
|
|
* @return \MongoDB\Collection |
171
|
|
|
*/ |
172
|
|
|
private static function getMongoCollection() |
173
|
|
|
{ |
174
|
|
|
$collection = (new \MongoDB\Client())->selectDatabase('testing')->selectCollection('cache'); |
175
|
|
|
$collection->drop(); |
176
|
|
|
$collection->createIndex(['expires' => 1], ['expireAfterSeconds' => 0]); |
177
|
|
|
return $collection; |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
|
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.