Reputation: 11
I tried using aioresponses to mock ClientSession POST request. But i get cannot connect to host sever. I am just using aiohttp client and not server. Also i do not want to pass in the fake session as a parameter to the test function. Is there a way to do this ?
Upvotes: 1
Views: 5898
Reputation: 107
I think you should use aioresponses
to mock the whole url of the endpoint of the remote host.
Let's suppose, that we are going to mock the external service like Telegram Bot API server. We want to test method sendMessage
of our client library ClientTgBot
which sends POST request.
Out project structure is like:
/app
- __init__.py
- client_tgbot.py
/tests/
- __init_.py
- conftest.py
- test_client_tgbot_unit.py
Let's assume that our app/client_tgbot.py
contains some logic, for example ClientTgBot with the method to test:
# app/client_tgbot.py
from aiohttp import ClientSession
class ClientTgBot:
def __init__(self, token):
self.token = token
async def sendMessage(self, chat_id, text):
"""
We want to test this method
without sending POST request to the host https://api.telegram.org
"""
url = "https://api.telegram.org/bot" + self.token + '/sendMessage'
async with ClientSession() as c:
response = await c.post(url, json={'chat_id': chat_id, 'text': text})
return response
Our fixtures:
# tests/conftest.py
import pytest
from aioresponses import aioresponses
from app.client_tgbot import ClientTgBot
@pytest.fixture
def mock_aioresponse():
with aioresponses() as m:
yield m
@pytest.fixture(scope="module")
def tg_token():
TEST_FAKE_TOKEN = "12345:TEST_FAKE_TOKEN"
yield TEST_FAKE_TOKEN
@pytest.fixture(scope="module")
def client_tgbot(tg_token):
client = ClientTgBot(tg_token)
yield client
Our test case:
# tests/test_client_tgbot_unit.py
import pytest
@pytest.mark.asyncio
async def test_sendMessage(tg_token, client_tgbot, mock_aioresponse):
JSON_RESPONSE_WRONG_MARKDOWN = {'ok': False, 'error_code': 400, 'description': "Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 3"}
mock_aioresponse.post(f"https://api.telegram.org/bot{tg_token}/sendMessage", payload=JSON_RESPONSE_WRONG_MARKDOWN)
response = await client_tgbot.sendMessage(435627225, "bot_sent")
assert response.status == 400
assert await response.json() == JSON_RESPONSE_WRONG_MARKDOWN
Install some libs:
pip3 install aiohttp aioresponses pytest pytest-asyncio
And run your tests:
python3 -m pytest -s . -vv
As you see, we've mocked the whole url https://api.telegram.org/bot12345:TEST_FAKE_TOKEN/sendMessage
without sending POST request to the real host. Also we don't have any fake session.
Upvotes: 6