11import asyncio
22from datetime import datetime , timezone
33from time import sleep
4- from unittest .mock import AsyncMock , Mock
4+ from unittest .mock import Mock
55
66import pytest
77from redis .auth .err import RequestTokenErr , TokenRenewalErr
@@ -29,48 +29,38 @@ class TestTokenManager:
2929 )
3030 def test_success_token_renewal (self , exp_refresh_ratio ):
3131 tokens = []
32+ errors = []
33+
34+ # Use a function to generate fresh tokens at request time
35+ # to avoid timing issues on slow CI runners
36+ def generate_token ():
37+ now = datetime .now (timezone .utc ).timestamp () * 1000
38+ return SimpleToken ("value" , now + 10000 , now , {"oid" : "test" })
39+
3240 mock_provider = Mock (spec = IdentityProviderInterface )
33- mock_provider .request_token .side_effect = [
34- SimpleToken (
35- "value" ,
36- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 100 ,
37- (datetime .now (timezone .utc ).timestamp () * 1000 ),
38- {"oid" : "test" },
39- ),
40- SimpleToken (
41- "value" ,
42- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 150 ,
43- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 50 ,
44- {"oid" : "test" },
45- ),
46- SimpleToken (
47- "value" ,
48- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 170 ,
49- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 70 ,
50- {"oid" : "test" },
51- ),
52- SimpleToken (
53- "value" ,
54- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 190 ,
55- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 90 ,
56- {"oid" : "test" },
57- ),
58- ]
41+ mock_provider .request_token .side_effect = (
42+ lambda * args , ** kwargs : generate_token ()
43+ )
5944
6045 def on_next (token ):
6146 nonlocal tokens
6247 tokens .append (token )
6348
49+ def on_error (err ):
50+ nonlocal errors
51+ errors .append (err )
52+
6453 mock_listener = Mock (spec = CredentialsListener )
6554 mock_listener .on_next = on_next
66- mock_listener .on_error = AsyncMock () # Add this line
55+ mock_listener .on_error = on_error
6756
6857 retry_policy = RetryPolicy (1 , 10 )
6958 config = TokenManagerConfig (exp_refresh_ratio , 0 , 1000 , retry_policy )
7059 mgr = TokenManager (mock_provider , config )
7160 mgr .start (mock_listener )
7261 sleep (0.1 )
7362
63+ assert len (errors ) == 0 , f"Unexpected errors: { errors } "
7464 assert len (tokens ) > 0
7565
7666 @pytest .mark .parametrize (
@@ -247,30 +237,32 @@ async def on_next(token):
247237
248238 def test_success_token_renewal_with_retry (self ):
249239 tokens = []
240+ errors = []
241+ call_count = [0 ]
242+
243+ # Use a function to generate fresh tokens at request time
244+ # to avoid timing issues on slow CI runners
245+ def request_token_side_effect (* args , ** kwargs ):
246+ call_count [0 ] += 1
247+ if call_count [0 ] <= 2 :
248+ raise RequestTokenErr ("Simulated failure" )
249+ now = datetime .now (timezone .utc ).timestamp () * 1000
250+ return SimpleToken ("value" , now + 10000 , now , {"oid" : "test" })
251+
250252 mock_provider = Mock (spec = IdentityProviderInterface )
251- mock_provider .request_token .side_effect = [
252- RequestTokenErr ,
253- RequestTokenErr ,
254- SimpleToken (
255- "value" ,
256- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 100 ,
257- (datetime .now (timezone .utc ).timestamp () * 1000 ),
258- {"oid" : "test" },
259- ),
260- SimpleToken (
261- "value" ,
262- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 100 ,
263- (datetime .now (timezone .utc ).timestamp () * 1000 ),
264- {"oid" : "test" },
265- ),
266- ]
253+ mock_provider .request_token .side_effect = request_token_side_effect
267254
268255 def on_next (token ):
269256 nonlocal tokens
270257 tokens .append (token )
271258
259+ def on_error (err ):
260+ nonlocal errors
261+ errors .append (err )
262+
272263 mock_listener = Mock (spec = CredentialsListener )
273264 mock_listener .on_next = on_next
265+ mock_listener .on_error = on_error
274266
275267 retry_policy = RetryPolicy (3 , 10 )
276268 config = TokenManagerConfig (1 , 0 , 1000 , retry_policy )
@@ -280,37 +272,39 @@ def on_next(token):
280272 # due to additional token renewal.
281273 sleep (0.08 )
282274
275+ assert len (errors ) == 0 , f"Unexpected errors: { errors } "
283276 assert mock_provider .request_token .call_count > 0
284277 assert len (tokens ) > 0
285278
286279 @pytest .mark .asyncio
287280 async def test_async_success_token_renewal_with_retry (self ):
288281 tokens = []
282+ errors = []
283+ call_count = [0 ]
284+
285+ # Use a function to generate fresh tokens at request time
286+ # to avoid timing issues on slow CI runners
287+ def request_token_side_effect (* args , ** kwargs ):
288+ call_count [0 ] += 1
289+ if call_count [0 ] <= 2 :
290+ raise RequestTokenErr ("Simulated failure" )
291+ now = datetime .now (timezone .utc ).timestamp () * 1000
292+ return SimpleToken ("value" , now + 10000 , now , {"oid" : "test" })
293+
289294 mock_provider = Mock (spec = IdentityProviderInterface )
290- mock_provider .request_token .side_effect = [
291- RequestTokenErr ,
292- RequestTokenErr ,
293- SimpleToken (
294- "value" ,
295- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 100 ,
296- (datetime .now (timezone .utc ).timestamp () * 1000 ),
297- {"oid" : "test" },
298- ),
299- SimpleToken (
300- "value" ,
301- (datetime .now (timezone .utc ).timestamp () * 1000 ) + 100 ,
302- (datetime .now (timezone .utc ).timestamp () * 1000 ),
303- {"oid" : "test" },
304- ),
305- ]
295+ mock_provider .request_token .side_effect = request_token_side_effect
306296
307297 async def on_next (token ):
308298 nonlocal tokens
309299 tokens .append (token )
310300
301+ async def on_error (err ):
302+ nonlocal errors
303+ errors .append (err )
304+
311305 mock_listener = Mock (spec = CredentialsListener )
312306 mock_listener .on_next = on_next
313- mock_listener .on_error = None
307+ mock_listener .on_error = on_error
314308
315309 retry_policy = RetryPolicy (3 , 10 )
316310 config = TokenManagerConfig (1 , 0 , 1000 , retry_policy )
@@ -320,6 +314,7 @@ async def on_next(token):
320314 # due to additional token renewal.
321315 await asyncio .sleep (0.08 )
322316
317+ assert len (errors ) == 0 , f"Unexpected errors: { errors } "
323318 assert mock_provider .request_token .call_count > 0
324319 assert len (tokens ) > 0
325320
0 commit comments