@@ -44,6 +44,9 @@ def reset_cache():
44
44
auth_methods ._token_cache = original_cache
45
45
46
46
47
+
48
+
49
+
47
50
@pytest .mark .asyncio
48
51
class TestAsyncAuthMethods :
49
52
"""Tests for asynchronous Google ID token fetching."""
@@ -61,7 +64,8 @@ async def test_aget_google_id_token_success_first_call(
61
64
mock_fetch .return_value = MOCK_ID_TOKEN
62
65
mock_verify .return_value = {"exp" : MOCK_EXPIRY_TIMESTAMP }
63
66
64
- token = await auth_methods .aget_google_id_token (MOCK_AUDIENCE )
67
+ token_getter = auth_methods .aget_google_id_token (MOCK_AUDIENCE )
68
+ token = await token_getter ()
65
69
66
70
mock_default .assert_called_once ()
67
71
mock_fetch .assert_called_once_with (ANY , MOCK_AUDIENCE )
@@ -72,15 +76,14 @@ async def test_aget_google_id_token_success_first_call(
72
76
@patch ("toolbox_core.auth_methods.google.auth.default" )
73
77
async def test_aget_google_id_token_success_uses_cache (self , mock_default ):
74
78
"""Tests that subsequent calls use the cached token if valid."""
75
- # Prime the cache with a valid token
76
79
auth_methods ._token_cache ["token" ] = MOCK_ID_TOKEN
77
80
auth_methods ._token_cache ["expires_at" ] = auth_methods .datetime .now (
78
81
auth_methods .timezone .utc
79
82
) + auth_methods .timedelta (hours = 1 )
80
83
81
- token = await auth_methods .aget_google_id_token (MOCK_AUDIENCE )
84
+ token_getter = auth_methods .aget_google_id_token (MOCK_AUDIENCE )
85
+ token = await token_getter ()
82
86
83
- # The underlying auth function should not be called if cache is valid
84
87
mock_default .assert_not_called ()
85
88
assert token == f"{ auth_methods .BEARER_TOKEN_PREFIX } { MOCK_ID_TOKEN } "
86
89
@@ -97,14 +100,13 @@ async def test_aget_google_id_token_refreshes_expired_cache(
97
100
auth_methods ._token_cache ["token" ] = "expired_token"
98
101
auth_methods ._token_cache ["expires_at" ] = auth_methods .datetime .now (
99
102
auth_methods .timezone .utc
100
- ) - auth_methods .timedelta (
101
- seconds = 100
102
- ) # Expired
103
+ ) - auth_methods .timedelta (seconds = 100 )
103
104
104
105
mock_fetch .return_value = MOCK_ID_TOKEN
105
106
mock_verify .return_value = {"exp" : MOCK_EXPIRY_TIMESTAMP }
106
107
107
- token = await auth_methods .aget_google_id_token (MOCK_AUDIENCE )
108
+ token_getter = auth_methods .aget_google_id_token (MOCK_AUDIENCE )
109
+ token = await token_getter ()
108
110
109
111
mock_default .assert_called_once ()
110
112
mock_fetch .assert_called_once ()
@@ -122,8 +124,8 @@ async def test_aget_raises_if_no_audience_and_no_local_token(
122
124
"""Tests that the async function propagates the missing audience exception."""
123
125
error_msg = "You are not authenticating using User Credentials."
124
126
with pytest .raises (Exception , match = error_msg ):
125
- # Call without audience to trigger the error path
126
- await auth_methods . aget_google_id_token ()
127
+ token_getter = auth_methods . aget_google_id_token ()
128
+ await token_getter ()
127
129
128
130
mock_default .assert_called_once ()
129
131
mock_fetch .assert_not_called ()
@@ -149,7 +151,8 @@ def test_get_google_id_token_success_local_creds(
149
151
mock_request_instance = MagicMock ()
150
152
mock_request .return_value = mock_request_instance
151
153
152
- token = auth_methods .get_google_id_token (MOCK_AUDIENCE )
154
+ token_getter = auth_methods .get_google_id_token (MOCK_AUDIENCE )
155
+ token = token_getter ()
153
156
154
157
mock_default .assert_called_once_with ()
155
158
mock_session .assert_called_once_with (mock_creds )
@@ -167,7 +170,8 @@ def test_get_google_id_token_success_uses_cache(self, mock_default):
167
170
auth_methods .timezone .utc
168
171
) + auth_methods .timedelta (hours = 1 )
169
172
170
- token = auth_methods .get_google_id_token (MOCK_AUDIENCE )
173
+ token_getter = auth_methods .get_google_id_token (MOCK_AUDIENCE )
174
+ token = token_getter ()
171
175
172
176
mock_default .assert_not_called ()
173
177
assert token == f"{ auth_methods .BEARER_TOKEN_PREFIX } { MOCK_ID_TOKEN } "
@@ -185,7 +189,7 @@ def test_get_google_id_token_fetch_failure(
185
189
mock_fetch .side_effect = GoogleAuthError ("Fetch failed" )
186
190
187
191
with pytest .raises (GoogleAuthError , match = "Fetch failed" ):
188
- auth_methods .get_google_id_token (MOCK_AUDIENCE )
192
+ auth_methods .get_google_id_token (MOCK_AUDIENCE )()
189
193
190
194
assert auth_methods ._token_cache ["token" ] is None
191
195
mock_default .assert_called_once ()
@@ -208,15 +212,13 @@ def test_get_google_id_token_validation_failure(
208
212
with pytest .raises (
209
213
ValueError , match = "Failed to validate and cache the new token"
210
214
):
211
- auth_methods .get_google_id_token (MOCK_AUDIENCE )
215
+ auth_methods .get_google_id_token (MOCK_AUDIENCE )()
212
216
213
- # Verify cache is cleared on validation failure
214
217
assert auth_methods ._token_cache ["token" ] is None
215
218
216
219
@patch ("toolbox_core.auth_methods.id_token.fetch_id_token" )
217
220
@patch (
218
221
"toolbox_core.auth_methods.google.auth.default" ,
219
- # Simulate credentials that DON'T have a pre-existing id_token
220
222
return_value = (MagicMock (id_token = None ), MOCK_PROJECT_ID ),
221
223
)
222
224
def test_get_raises_if_no_audience_and_no_local_token (
@@ -225,8 +227,7 @@ def test_get_raises_if_no_audience_and_no_local_token(
225
227
"""Tests exception is raised if audience is required but not provided."""
226
228
error_msg = "You are not authenticating using User Credentials."
227
229
with pytest .raises (Exception , match = error_msg ):
228
- # Call without an audience to trigger the error path
229
- auth_methods .get_google_id_token ()
230
+ auth_methods .get_google_id_token ()()
230
231
231
232
mock_default .assert_called_once ()
232
- mock_fetch .assert_not_called ()
233
+ mock_fetch .assert_not_called ()
0 commit comments