- test_fetch_cat.py: 10 тестов (def → async def, asyncio.run → await) - test_fetch_rss.py: 21 тест (def → async def, asyncio.run → await) - test_fetch_weather.py: 19 тест (def → async def, asyncio.run → await) - Удалён лишний import asyncio из тестовых файлов - Больше не создаётся новый event loop на каждый тест - RateLimiter (asyncio.Lock) теперь корректно работает в одном loop 230 тестов проходят.
102 lines
4.3 KiB
Python
102 lines
4.3 KiB
Python
import json
|
||
import pytest
|
||
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):
|
||
"""Успешный ответ с 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."""
|
||
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):
|
||
"""HTTP-ошибка (raise_for_status) должна вернуть None."""
|
||
import requests
|
||
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):
|
||
"""ConnectionError должна вернуть None."""
|
||
from requests.exceptions import ConnectionError
|
||
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):
|
||
"""Timeout должна вернуть None."""
|
||
from requests.exceptions import Timeout
|
||
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):
|
||
"""SSLError должна вернуть None."""
|
||
from requests.exceptions import SSLError
|
||
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):
|
||
"""Ошибка парсинга JSON должна вернуть None."""
|
||
import requests
|
||
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):
|
||
"""Отсутствие ключа '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):
|
||
"""Общий RequestException должен вернуть None."""
|
||
import requests
|
||
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):
|
||
"""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"
|