Skip to content

Commit 2392bf7

Browse files
kevinquinnyoramsey
andauthored
Allow time to be set for test purposes (#852)
This just adds a static method for test purposes so that downstream code can more easily assert an exact `AccessToken` object in their tests. Since the calls to `time()` are non-deterministic, downstream tests are forced to mock, or do looser assertions on the `expires` property. Co-authored-by: Ben Ramsey <[email protected]>
1 parent 937c0ac commit 2392bf7

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

src/Token/AccessToken.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,40 @@ class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInter
4949
*/
5050
protected $values = [];
5151

52+
/**
53+
* @var int
54+
*/
55+
private static $timeNow;
56+
57+
/**
58+
* Set the time now. This should only be used for testing purposes.
59+
*
60+
* @param int $timeNow the time in seconds since epoch
61+
* @return void
62+
*/
63+
public static function setTimeNow($timeNow)
64+
{
65+
self::$timeNow = $timeNow;
66+
}
67+
68+
/**
69+
* Reset the time now if it was set for test purposes.
70+
*
71+
* @return void
72+
*/
73+
public static function resetTimeNow()
74+
{
75+
self::$timeNow = null;
76+
}
77+
78+
/**
79+
* @return int
80+
*/
81+
public function getTimeNow()
82+
{
83+
return self::$timeNow ? self::$timeNow : time();
84+
}
85+
5286
/**
5387
* Constructs an access token.
5488
*
@@ -80,14 +114,14 @@ public function __construct(array $options = [])
80114
throw new \InvalidArgumentException('expires_in value must be an integer');
81115
}
82116

83-
$this->expires = $options['expires_in'] != 0 ? time() + $options['expires_in'] : 0;
117+
$this->expires = $options['expires_in'] != 0 ? $this->getTimeNow() + $options['expires_in'] : 0;
84118
} elseif (!empty($options['expires'])) {
85119
// Some providers supply the seconds until expiration rather than
86120
// the exact timestamp. Take a best guess at which we received.
87121
$expires = $options['expires'];
88122

89123
if (!$this->isExpirationTimestamp($expires)) {
90-
$expires += time();
124+
$expires += $this->getTimeNow();
91125
}
92126

93127
$this->expires = $expires;

test/src/Token/AccessTokenTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,27 @@
1010

1111
class AccessTokenTest extends TestCase
1212
{
13+
/**
14+
* BC teardown.
15+
*
16+
* This is for backwards compatibility of older PHP versions. Ideally we would just implement a tearDown() here but
17+
* older PHP versions this library supports don't have return typehint support, so this is the workaround.
18+
*
19+
* @return void
20+
*/
21+
private static function tearDownForBackwardsCompatibility()
22+
{
23+
/* reset the test double time if it was set */
24+
AccessToken::resetTimeNow();
25+
}
26+
1327
public function testInvalidRefreshToken()
1428
{
1529
$this->expectException(InvalidArgumentException::class);
1630

1731
$token = $this->getAccessToken(['invalid_access_token' => 'none']);
32+
33+
self::tearDownForBackwardsCompatibility();
1834
}
1935

2036
protected function getAccessToken($options = [])
@@ -32,6 +48,49 @@ public function testExpiresInCorrection()
3248
$this->assertNotNull($expires);
3349
$this->assertGreaterThan(time(), $expires);
3450
$this->assertLessThan(time() + 200, $expires);
51+
52+
self::tearDownForBackwardsCompatibility();
53+
}
54+
55+
public function testExpiresInCorrectionUsingSetTimeNow()
56+
{
57+
/* set fake time at 2020-01-01 00:00:00 */
58+
AccessToken::setTimeNow(1577836800);
59+
$options = ['access_token' => 'access_token', 'expires_in' => 100];
60+
$token = $this->getAccessToken($options);
61+
62+
$expires = $token->getExpires();
63+
64+
$this->assertNotNull($expires);
65+
$this->assertEquals(1577836900, $expires);
66+
67+
self::tearDownForBackwardsCompatibility();
68+
}
69+
70+
public function testSetTimeNow()
71+
{
72+
AccessToken::setTimeNow(1577836800);
73+
$timeNow = $this->getAccessToken(['access_token' => 'asdf'])->getTimeNow();
74+
75+
$this->assertEquals(1577836800, $timeNow);
76+
77+
self::tearDownForBackwardsCompatibility();
78+
}
79+
80+
public function testResetTimeNow()
81+
{
82+
AccessToken::setTimeNow(1577836800);
83+
$token = $this->getAccessToken(['access_token' => 'asdf']);
84+
85+
$this->assertEquals(1577836800, $token->getTimeNow());
86+
AccessToken::resetTimeNow();
87+
88+
$this->assertNotEquals(1577836800, $token->getTimeNow());
89+
90+
$timeBeforeAssertion = time();
91+
$this->assertGreaterThanOrEqual($timeBeforeAssertion, $token->getTimeNow());
92+
93+
self::tearDownForBackwardsCompatibility();
3594
}
3695

3796
public function testExpiresPastTimestamp()
@@ -45,6 +104,8 @@ public function testExpiresPastTimestamp()
45104
$token = $this->getAccessToken($options);
46105

47106
$this->assertFalse($token->hasExpired());
107+
108+
self::tearDownForBackwardsCompatibility();
48109
}
49110

50111
public function testGetRefreshToken()
@@ -58,6 +119,8 @@ public function testGetRefreshToken()
58119
$refreshToken = $token->getRefreshToken();
59120

60121
$this->assertEquals($options['refresh_token'], $refreshToken);
122+
123+
self::tearDownForBackwardsCompatibility();
61124
}
62125

63126
public function testHasNotExpiredWhenPropertySetInFuture()
@@ -75,6 +138,8 @@ public function testHasNotExpiredWhenPropertySetInFuture()
75138
->andReturn($expectedExpires);
76139

77140
$this->assertFalse($token->hasExpired());
141+
142+
self::tearDownForBackwardsCompatibility();
78143
}
79144

80145
public function testHasExpiredWhenPropertySetInPast()
@@ -92,6 +157,8 @@ public function testHasExpiredWhenPropertySetInPast()
92157
->andReturn($expectedExpires);
93158

94159
$this->assertTrue($token->hasExpired());
160+
161+
self::tearDownForBackwardsCompatibility();
95162
}
96163

97164
public function testCannotReportExpiredWhenNoExpirationSet()
@@ -104,6 +171,8 @@ public function testCannotReportExpiredWhenNoExpirationSet()
104171
$this->expectException(RuntimeException::class);
105172

106173
$hasExpired = $token->hasExpired();
174+
175+
self::tearDownForBackwardsCompatibility();
107176
}
108177

109178
public function testInvalidExpiresIn()
@@ -116,6 +185,8 @@ public function testInvalidExpiresIn()
116185
$this->expectException(InvalidArgumentException::class);
117186

118187
$token = $this->getAccessToken($options);
188+
189+
self::tearDownForBackwardsCompatibility();
119190
}
120191

121192

@@ -132,6 +203,8 @@ public function testJsonSerializable()
132203
$jsonToken = json_encode($token);
133204

134205
$this->assertEquals($options, json_decode($jsonToken, true));
206+
207+
self::tearDownForBackwardsCompatibility();
135208
}
136209

137210
public function testValues()
@@ -151,5 +224,7 @@ public function testValues()
151224
$this->assertTrue(is_array($values));
152225
$this->assertArrayHasKey('custom_thing', $values);
153226
$this->assertSame($options['custom_thing'], $values['custom_thing']);
227+
228+
self::tearDownForBackwardsCompatibility();
154229
}
155230
}

0 commit comments

Comments
 (0)