125 lines
5.6 KiB
Python
125 lines
5.6 KiB
Python
import requests
|
||
from requests.exceptions import ConnectionError, Timeout, SSLError
|
||
from unittest.mock import patch, MagicMock
|
||
from utils.cat import fetch_cat
|
||
|
||
|
||
class TestFetchCat:
|
||
"""Тесты функции fetch_cat() — получение URL случайного котика."""
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_success(self, mock_get) -> None:
|
||
"""Успешный ответ с URL должен вернуть строку."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = [{"url": "https://example.com/cat.jpg"}]
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result == "https://example.com/cat.jpg"
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_empty_array(self, mock_get) -> None:
|
||
"""Пустой массив должен вернуть None."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = []
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_http_error(self, mock_get) -> None:
|
||
"""HTTP-ошибка (raise_for_status) должна вернуть None."""
|
||
mock_response = MagicMock()
|
||
mock_response.raise_for_status.side_effect = requests.HTTPError("404 Not Found")
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_connection_error(self, mock_get) -> None:
|
||
"""ConnectionError должна вернуть None."""
|
||
mock_get.side_effect = ConnectionError("No connection")
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_timeout(self, mock_get) -> None:
|
||
"""Timeout должна вернуть None."""
|
||
mock_get.side_effect = Timeout("Request timed out")
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_ssl_error(self, mock_get) -> None:
|
||
"""SSLError должна вернуть None."""
|
||
mock_get.side_effect = SSLError("SSL handshake failed")
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_json_parse_error(self, mock_get) -> None:
|
||
"""Ошибка парсинга JSON должна вернуть None."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.side_effect = requests.JSONDecodeError(
|
||
"Expecting value", "", 0
|
||
)
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_missing_url_key(self, mock_get) -> None:
|
||
"""Отсутствие ключа 'url' в ответе должно вернуть None."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = [{"error": "no image"}]
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_request_exception(self, mock_get) -> None:
|
||
"""Общий RequestException должен вернуть None."""
|
||
mock_get.side_effect = requests.RequestException("Generic error")
|
||
result = await fetch_cat()
|
||
assert result is None
|
||
|
||
@patch("utils.cat._session.get")
|
||
async def test_fetch_cat_url_with_special_chars(self, mock_get) -> None:
|
||
"""URL со спецсимволами должен вернуться как есть."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = [
|
||
{"url": "https://example.com/cat?w=100&h=200"}
|
||
]
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
result = await fetch_cat()
|
||
assert result == "https://example.com/cat?w=100&h=200"
|
||
|
||
@patch("utils.cat._session.get")
|
||
@patch("utils.cat._cat_api_key", "test-api-key-123")
|
||
async def test_fetch_cat_sends_api_key_header(self, mock_get) -> None:
|
||
"""При заданном CAT_API_KEY должен передаваться заголовок x-api-key."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = [{"url": "https://example.com/cat.jpg"}]
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
await fetch_cat()
|
||
# Проверяем, что headers переданы с x-api-key
|
||
call_kwargs = mock_get.call_args
|
||
assert call_kwargs[1].get("headers") == {"x-api-key": "test-api-key-123"}
|
||
|
||
@patch("utils.cat._session.get")
|
||
@patch("utils.cat._cat_api_key", None)
|
||
async def test_fetch_cat_no_api_key_header(self, mock_get) -> None:
|
||
"""При отсутствии CAT_API_KEY заголовок x-api-key не передаётся."""
|
||
mock_response = MagicMock()
|
||
mock_response.json.return_value = [{"url": "https://example.com/cat.jpg"}]
|
||
mock_response.raise_for_status = MagicMock()
|
||
mock_get.return_value = mock_response
|
||
await fetch_cat()
|
||
call_kwargs = mock_get.call_args
|
||
assert call_kwargs[1].get("headers") is None
|