Skip to content
This repository was archived by the owner on Mar 6, 2026. It is now read-only.

Commit 1e1ed0a

Browse files
committed
support AsyncMock for 3.7
1 parent 5d9b955 commit 1e1ed0a

6 files changed

Lines changed: 88 additions & 59 deletions

File tree

tests/transport/aio/test_aiohttp.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
# limitations under the License.
1414

1515
import asyncio
16-
from unittest.mock import AsyncMock, Mock, patch
17-
16+
from unittest.mock import Mock, patch
17+
try:
18+
from unittest.mock import AsyncMock
19+
except ImportError:
20+
# Fallback for Python < 3.8
21+
from mock import AsyncMock
1822
from aioresponses import aioresponses # type: ignore
1923
import pytest # type: ignore
2024
import pytest_asyncio # type: ignore

tests_async/oauth2/test__client_async.py

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
import http.client as http_client
1717
import json
1818
from unittest import mock
19+
try:
20+
from unittest.mock import AsyncMock
21+
except ImportError:
22+
# Fallback for Python < 3.8
23+
from mock import AsyncMock
1924
import urllib
2025

2126
import pytest # type: ignore
@@ -29,13 +34,13 @@
2934

3035

3136
def make_request(response_data, status=http_client.OK, text=False):
32-
response = mock.AsyncMock(spec=["transport.Response"])
37+
response = AsyncMock(spec=["transport.Response"])
3338
response.status = status
3439
data = response_data if text else json.dumps(response_data).encode("utf-8")
35-
response.data = mock.AsyncMock(spec=["__call__", "read"])
36-
response.data.read = mock.AsyncMock(spec=["__call__"], return_value=data)
37-
response.content = mock.AsyncMock(spec=["__call__"], return_value=data)
38-
request = mock.AsyncMock(spec=["transport.Request"])
40+
response.data = AsyncMock(spec=["__call__", "read"])
41+
response.data.read = AsyncMock(spec=["__call__"], return_value=data)
42+
response.content = AsyncMock(spec=["__call__"], return_value=data)
43+
request = AsyncMock(spec=["transport.Request"])
3944
request.return_value = response
4045
return request
4146

@@ -142,21 +147,21 @@ async def test__token_endpoint_request_internal_failure_error():
142147

143148
@pytest.mark.asyncio
144149
async def test__token_endpoint_request_internal_failure_and_retry_failure_error():
145-
retryable_error = mock.AsyncMock(spec=["transport.Response"])
150+
retryable_error = AsyncMock(spec=["transport.Response"])
146151
retryable_error.status = http_client.BAD_REQUEST
147152
data = json.dumps({"error_description": "internal_failure"}).encode("utf-8")
148-
retryable_error.data = mock.AsyncMock(spec=["__call__", "read"])
149-
retryable_error.data.read = mock.AsyncMock(spec=["__call__"], return_value=data)
150-
retryable_error.content = mock.AsyncMock(spec=["__call__"], return_value=data)
153+
retryable_error.data = AsyncMock(spec=["__call__", "read"])
154+
retryable_error.data.read = AsyncMock(spec=["__call__"], return_value=data)
155+
retryable_error.content = AsyncMock(spec=["__call__"], return_value=data)
151156

152-
unretryable_error = mock.AsyncMock(spec=["transport.Response"])
157+
unretryable_error = AsyncMock(spec=["transport.Response"])
153158
unretryable_error.status = http_client.BAD_REQUEST
154159
data = json.dumps({"error_description": "invalid_scope"}).encode("utf-8")
155-
unretryable_error.data = mock.AsyncMock(spec=["__call__", "read"])
156-
unretryable_error.data.read = mock.AsyncMock(spec=["__call__"], return_value=data)
157-
unretryable_error.content = mock.AsyncMock(spec=["__call__"], return_value=data)
160+
unretryable_error.data = AsyncMock(spec=["__call__", "read"])
161+
unretryable_error.data.read = AsyncMock(spec=["__call__"], return_value=data)
162+
unretryable_error.content = AsyncMock(spec=["__call__"], return_value=data)
158163

159-
request = mock.AsyncMock(spec=["transport.Request"])
164+
request = AsyncMock(spec=["transport.Request"])
160165
request.side_effect = [retryable_error, retryable_error, unretryable_error]
161166

162167
with pytest.raises(exceptions.RefreshError):
@@ -170,21 +175,21 @@ async def test__token_endpoint_request_internal_failure_and_retry_failure_error(
170175

171176
@pytest.mark.asyncio
172177
async def test__token_endpoint_request_internal_failure_and_retry_succeeds():
173-
retryable_error = mock.AsyncMock(spec=["transport.Response"])
178+
retryable_error = AsyncMock(spec=["transport.Response"])
174179
retryable_error.status = http_client.BAD_REQUEST
175180
data = json.dumps({"error_description": "internal_failure"}).encode("utf-8")
176-
retryable_error.data = mock.AsyncMock(spec=["__call__", "read"])
177-
retryable_error.data.read = mock.AsyncMock(spec=["__call__"], return_value=data)
178-
retryable_error.content = mock.AsyncMock(spec=["__call__"], return_value=data)
181+
retryable_error.data = AsyncMock(spec=["__call__", "read"])
182+
retryable_error.data.read = AsyncMock(spec=["__call__"], return_value=data)
183+
retryable_error.content = AsyncMock(spec=["__call__"], return_value=data)
179184

180-
response = mock.AsyncMock(spec=["transport.Response"])
185+
response = AsyncMock(spec=["transport.Response"])
181186
response.status = http_client.OK
182187
data = json.dumps({"hello": "world"}).encode("utf-8")
183-
response.data = mock.AsyncMock(spec=["__call__", "read"])
184-
response.data.read = mock.AsyncMock(spec=["__call__"], return_value=data)
185-
response.content = mock.AsyncMock(spec=["__call__"], return_value=data)
188+
response.data = AsyncMock(spec=["__call__", "read"])
189+
response.data.read = AsyncMock(spec=["__call__"], return_value=data)
190+
response.content = AsyncMock(spec=["__call__"], return_value=data)
186191

187-
request = mock.AsyncMock(spec=["transport.Request"])
192+
request = AsyncMock(spec=["transport.Request"])
188193
request.side_effect = [retryable_error, response]
189194

190195
_ = await _client._token_endpoint_request(
@@ -399,7 +404,7 @@ async def test_jwt_grant_retry_with_retry(
399404
mock_token_endpoint_request, mock_expiry, can_retry
400405
):
401406
_ = await _client.jwt_grant(
402-
mock.AsyncMock(), mock.Mock(), mock.Mock(), can_retry=can_retry
407+
AsyncMock(), mock.Mock(), mock.Mock(), can_retry=can_retry
403408
)
404409
mock_token_endpoint_request.assert_called_with(
405410
mock.ANY, mock.ANY, mock.ANY, can_retry=can_retry
@@ -426,7 +431,7 @@ async def test_id_token_jwt_grant_retry_with_retry(
426431
mock_token_endpoint_request, mock_jwt_decode, can_retry
427432
):
428433
_ = await _client.id_token_jwt_grant(
429-
mock.AsyncMock(), mock.AsyncMock(), mock.AsyncMock(), can_retry=can_retry
434+
AsyncMock(), AsyncMock(), AsyncMock(), can_retry=can_retry
430435
)
431436
mock_token_endpoint_request.assert_called_with(
432437
mock.ANY, mock.ANY, mock.ANY, can_retry=can_retry
@@ -440,11 +445,11 @@ async def test_refresh_grant_retry_default(
440445
mock_token_endpoint_request, mock_parse_expiry
441446
):
442447
_ = await _client.refresh_grant(
443-
mock.AsyncMock(),
444-
mock.AsyncMock(),
445-
mock.AsyncMock(),
446-
mock.AsyncMock(),
447-
mock.AsyncMock(),
448+
AsyncMock(),
449+
AsyncMock(),
450+
AsyncMock(),
451+
AsyncMock(),
452+
AsyncMock(),
448453
)
449454
mock_token_endpoint_request.assert_called_with(
450455
mock.ANY, mock.ANY, mock.ANY, can_retry=True
@@ -459,11 +464,11 @@ async def test_refresh_grant_retry_with_retry(
459464
mock_token_endpoint_request, mock_parse_expiry, can_retry
460465
):
461466
_ = await _client.refresh_grant(
462-
mock.AsyncMock(),
463-
mock.AsyncMock(),
464-
mock.AsyncMock(),
465-
mock.AsyncMock(),
466-
mock.AsyncMock(),
467+
AsyncMock(),
468+
AsyncMock(),
469+
AsyncMock(),
470+
AsyncMock(),
471+
AsyncMock(),
467472
can_retry=can_retry,
468473
)
469474
mock_token_endpoint_request.assert_called_with(
@@ -481,10 +486,10 @@ async def test__token_endpoint_request_no_throw_with_retry(can_retry):
481486

482487
_ = await _client._token_endpoint_request_no_throw(
483488
mock_request,
484-
mock.AsyncMock(),
489+
AsyncMock(),
485490
"body",
486-
mock.AsyncMock(),
487-
mock.AsyncMock(),
491+
AsyncMock(),
492+
AsyncMock(),
488493
can_retry=can_retry,
489494
)
490495

tests_async/oauth2/test_credentials_async.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
import pickle
1919
import sys
2020
from unittest import mock
21+
try:
22+
from unittest.mock import AsyncMock
23+
except ImportError:
24+
# Fallback for Python < 3.8
25+
from mock import AsyncMock
2126

2227
import pytest # type: ignore
2328

@@ -82,7 +87,7 @@ async def test_refresh_success(self, unused_utcnow, refresh_grant):
8287
rapt_token,
8388
)
8489

85-
request = mock.AsyncMock(spec=["transport.Request"])
90+
request = AsyncMock(spec=["transport.Request"])
8691
creds = self.make_credentials()
8792

8893
# Refresh credentials
@@ -112,7 +117,7 @@ async def test_refresh_success(self, unused_utcnow, refresh_grant):
112117

113118
@pytest.mark.asyncio
114119
async def test_refresh_no_refresh_token(self):
115-
request = mock.AsyncMock(spec=["transport.Request"])
120+
request = AsyncMock(spec=["transport.Request"])
116121
credentials_ = _credentials_async.Credentials(token=None, refresh_token=None)
117122

118123
with pytest.raises(exceptions.RefreshError, match="necessary fields"):
@@ -147,7 +152,7 @@ async def test_credentials_with_scopes_requested_refresh_success(
147152
rapt_token,
148153
)
149154

150-
request = mock.AsyncMock(spec=["transport.Request"])
155+
request = AsyncMock(spec=["transport.Request"])
151156
creds = _credentials_async.Credentials(
152157
token=None,
153158
refresh_token=self.REFRESH_TOKEN,
@@ -211,7 +216,7 @@ async def test_credentials_with_scopes_returned_refresh_success(
211216
rapt_token,
212217
)
213218

214-
request = mock.AsyncMock(spec=["transport.Request"])
219+
request = AsyncMock(spec=["transport.Request"])
215220
creds = _credentials_async.Credentials(
216221
token=None,
217222
refresh_token=self.REFRESH_TOKEN,
@@ -278,7 +283,7 @@ async def test_credentials_with_scopes_refresh_failure_raises_refresh_error(
278283
rapt_token,
279284
)
280285

281-
request = mock.AsyncMock(spec=["transport.Request"])
286+
request = AsyncMock(spec=["transport.Request"])
282287
creds = _credentials_async.Credentials(
283288
token=None,
284289
refresh_token=self.REFRESH_TOKEN,

tests_async/oauth2/test_id_token.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
import json
1616
import os
1717
from unittest import mock
18+
try:
19+
from unittest.mock import AsyncMock
20+
except ImportError:
21+
# Fallback for Python < 3.8
22+
from mock import AsyncMock
1823

1924
import pytest # type: ignore
2025

@@ -28,16 +33,16 @@
2833

2934

3035
def make_request(status, data=None):
31-
response = mock.AsyncMock(spec=["transport.Response"])
36+
response = AsyncMock(spec=["transport.Response"])
3237
response.status = status
3338

3439
if data is not None:
35-
response.data = mock.AsyncMock(spec=["__call__", "read"])
36-
response.content = mock.AsyncMock(
40+
response.data = AsyncMock(spec=["__call__", "read"])
41+
response.content = AsyncMock(
3742
spec=["__call__"], return_value=json.dumps(data).encode("utf-8")
3843
)
3944

40-
request = mock.AsyncMock(spec=["transport.Request"])
45+
request = AsyncMock(spec=["transport.Request"])
4146
request.return_value = response
4247
return request
4348

@@ -223,7 +228,7 @@ def mock_init(self, request, audience, use_metadata_identity_endpoint):
223228
__init__=mock_init,
224229
refresh=mock.Mock(),
225230
):
226-
request = mock.AsyncMock()
231+
request = AsyncMock()
227232
token = await id_token.fetch_id_token(
228233
request, "https://pubsub.googleapis.com"
229234
)
@@ -240,7 +245,7 @@ async def mock_refresh(self, request):
240245
with mock.patch.object(
241246
_service_account_async.IDTokenCredentials, "refresh", mock_refresh
242247
):
243-
request = mock.AsyncMock()
248+
request = AsyncMock()
244249
token = await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
245250
assert token == "id_token"
246251

@@ -254,15 +259,15 @@ async def test_fetch_id_token_no_cred_exists(monkeypatch):
254259
side_effect=exceptions.TransportError(),
255260
):
256261
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
257-
request = mock.AsyncMock()
262+
request = AsyncMock()
258263
await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
259264
assert excinfo.match(
260265
r"Neither metadata server or valid service account credentials are found."
261266
)
262267

263268
with mock.patch("google.auth.compute_engine._metadata.ping", return_value=False):
264269
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
265-
request = mock.AsyncMock()
270+
request = AsyncMock()
266271
await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
267272
assert excinfo.match(
268273
r"Neither metadata server or valid service account credentials are found."
@@ -277,7 +282,7 @@ async def test_fetch_id_token_invalid_cred_file(monkeypatch):
277282
monkeypatch.setenv(environment_vars.CREDENTIALS, not_json_file)
278283

279284
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
280-
request = mock.AsyncMock()
285+
request = AsyncMock()
281286
await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
282287
assert excinfo.match(
283288
r"GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials."
@@ -293,7 +298,7 @@ async def test_fetch_id_token_invalid_cred_type(monkeypatch):
293298

294299
with mock.patch("google.auth.compute_engine._metadata.ping", return_value=False):
295300
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
296-
request = mock.AsyncMock()
301+
request = AsyncMock()
297302
await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
298303
assert excinfo.match(
299304
r"Neither metadata server or valid service account credentials are found."
@@ -308,7 +313,7 @@ async def test_fetch_id_token_invalid_cred_path(monkeypatch):
308313
monkeypatch.setenv(environment_vars.CREDENTIALS, not_json_file)
309314

310315
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
311-
request = mock.AsyncMock()
316+
request = AsyncMock()
312317
await id_token.fetch_id_token(request, "https://pubsub.googleapis.com")
313318
assert excinfo.match(
314319
r"GOOGLE_APPLICATION_CREDENTIALS path is either not found or invalid."

tests_async/oauth2/test_reauth_async.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
import copy
1616
from unittest import mock
17+
try:
18+
from unittest.mock import AsyncMock
19+
except ImportError:
20+
# Fallback for Python < 3.8
21+
from mock import AsyncMock
1722

1823
import pytest # type: ignore
1924

@@ -22,7 +27,7 @@
2227
from google.oauth2 import reauth
2328

2429

25-
MOCK_REQUEST = mock.AsyncMock(spec=["transport.Request"])
30+
MOCK_REQUEST = AsyncMock(spec=["transport.Request"])
2631
CHALLENGES_RESPONSE_TEMPLATE = {
2732
"status": "CHALLENGE_REQUIRED",
2833
"sessionId": "123",

tests_async/oauth2/test_service_account_async.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
import datetime
1616
from unittest import mock
17+
try:
18+
from unittest.mock import AsyncMock
19+
except ImportError:
20+
# Fallback for Python < 3.8
21+
from mock import AsyncMock
1722

1823
import pytest # type: ignore
1924

@@ -331,7 +336,7 @@ async def test_refresh_success(self, id_token_jwt_grant):
331336
{},
332337
)
333338

334-
request = mock.AsyncMock(spec=["transport.Request"])
339+
request = AsyncMock(spec=["transport.Request"])
335340

336341
# Refresh credentials
337342
await credentials.refresh(request)
@@ -363,7 +368,7 @@ async def test_before_request_refreshes(self, id_token_jwt_grant):
363368
_helpers.utcnow() + datetime.timedelta(seconds=500),
364369
None,
365370
)
366-
request = mock.AsyncMock(spec=["transport.Request"])
371+
request = AsyncMock(spec=["transport.Request"])
367372

368373
# Credentials should start as invalid
369374
assert not credentials.valid

0 commit comments

Comments
 (0)