![](/img/trans.png)
[英]How to mock aiohttp.client.ClientSession.get async context manager
[英]How do I Mock the coroutine json() when using aiohttp.ClientSession.get
我想從aiohttp.ClientSession.get方法中模擬json()協程。 它看起來返回一個異步生成器對象,在這個例子中我對如何模擬感到困惑。 這是我的代碼:
async def get_access_token():
async with aiohttp.ClientSession(auth=auth_credentials) as client:
async with client.get(auth_path, params={'grant_type': 'client_credentials'}) as auth_response:
assert auth_response.status == 200
auth_json = await auth_response.json()
return auth_json['access_token']
這是我模擬get方法的測試用例:
json_data = [{
'access_token': 'HSG9hsf328bJSWO82sl',
'expires_in': 86399,
'token_type': 'bearer'
}]
class AsyncMock:
async def __aenter__(self):
return self
async def __aexit__(self, *error_info):
return self
@pytest.mark.asyncio
async def test_wow_api_invalid_credentials(monkeypatch, mocker):
def mock_client_get(self, auth_path, params):
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = mocker.MagicMock(return_value=json_data)
return mock_response
monkeypatch.setattr('wow.aiohttp.ClientSession.get', mock_client_get)
result = await wow.get_access_token()
assert result == 'HSG9hsf328bJSWO82sl'
我認為問題可能出在mock_response.json()不可等待。 在我的示例中,我無法從非異步函數中調用await,因此我對如何執行此操作感到困惑。 我想將pytest和pytest-asyncio的測試庫保持在最低水平,以進行學習,並減少對第三方庫的依賴。
這是第1部分,但我建議您觀看第2部分。
我不確定我是否完全理解您的問題,因為使用async def
或@asyncio.coroutine
可以幫助您做到這一點。 實際上,我想將其寫為評論,但是有太多差異,我無法將其放入評論中。
import asyncio
json_ = [{
'access_token': 'HSG9hsf328bJSWO82sl',
'expires_in': 86399,
'token_type': 'bearer'
}]
async def response_from_sun():
return json_
class AsyncMock:
async def specify(self):
return self.json[0].get("access_token")
async def __aenter__(self):
return self
async def __aexit__(self, *error_info):
return self
async def mock_client_get():
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = await response_from_sun()
return mock_response
async def go():
resp = await mock_client_get()
result = await resp.specify()
assert result == 'HSG9hsf328bJSWO82sl'
asyncio.get_event_loop().run_until_complete(go())
第2部分
添加我的答案后,我發現您的mock_response
內容存在問題。 因為mock_response
不包含ClientResponse
具有的變量和函數。
編輯:我嘗試了很多次並觀看ClientSession的代碼,然后發現可以通過其參數指定新的響應類。 注意: connector=aiohttp.TCPConnector(verify_ssl=False)
是不必要的
import asyncio
import aiohttp
class Mock(aiohttp.ClientResponse):
print("Mock")
async def specify(self):
json_ = (await self.json()).get("hello")
return json_
async def go():
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=False),response_class=Mock) as session:
resp = await session.get("https://www.mocky.io/v2/5185415ba171ea3a00704eed")
result = await resp.specify()
print(result)
assert result == 'world'
asyncio.get_event_loop().run_until_complete(go())
我使它變得比需要的復雜。 我只是將json定義為AsyncMock的可等待屬性,該屬性返回json_data。 完整的代碼如下所示:
json_data = {
'access_token': 'HSG9hsf328bJSWO82sl',
'expires_in': 86399,
'token_type': 'bearer'
}
class AsyncMock:
async def __aenter__(self):
return self
async def __aexit__(self, *error_info):
return self
async def json(self):
return json_data
@pytest.mark.asyncio
async def test_wow_api_invalid_credentials(monkeypatch):
def mock_client_get(self, auth_path, params):
mock_response = AsyncMock()
mock_response.status = 200
return mock_response
monkeypatch.setattr('wow.aiohttp.ClientSession.get', mock_client_get)
result = await wow.get_access_token()
assert result == 'HSG9hsf328bJSWO82sl'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.