diff --git a/tests/test_morning_runner.py b/tests/test_morning_runner.py index 6a4511f..974526c 100644 --- a/tests/test_morning_runner.py +++ b/tests/test_morning_runner.py @@ -2,7 +2,7 @@ import asyncio from datetime import datetime -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock import discord import pytest @@ -16,25 +16,37 @@ class TestSchedulerInit: def test_init_sets_morning_time(self): """Инициализация должна устанавливать время.""" bot = AsyncMock() - scheduler = Scheduler(bot, "08:30") + mock_loop = MagicMock() + with patch("utils.morning_runner.tasks.loop", return_value=mock_loop): + scheduler = Scheduler(bot, "08:30") assert scheduler.morning_time == "08:30" def test_init_default_morning_time(self): """Инициализация с дефолтным временем.""" bot = AsyncMock() - scheduler = Scheduler(bot) + mock_loop = MagicMock() + with patch("utils.morning_runner.tasks.loop", return_value=mock_loop): + scheduler = Scheduler(bot) assert scheduler.morning_time == "07:00" def test_init_creates_loop(self): """Инициализация должна создавать loop.""" bot = AsyncMock() - scheduler = Scheduler(bot) + mock_loop = MagicMock() + with patch("utils.morning_runner.tasks.loop", return_value=mock_loop): + scheduler = Scheduler(bot) assert scheduler.morning_loop is not None class TestSchedulerCalculateNextRun: """Тесты расчёта следующего запуска.""" + @pytest.fixture(autouse=True) + def _mock_loop(self): + """Замокать tasks.loop, чтобы не создавать реальный coroutine.""" + with patch("utils.morning_runner.tasks.loop", return_value=MagicMock()): + yield + def test_next_run_today_before_time(self): """Если сейчас раньше времени — вернуть сегодня.""" bot = AsyncMock() @@ -69,6 +81,12 @@ class TestSchedulerCalculateNextRun: class TestSchedulerStartStop: """Тесты запуска/остановки планировщика.""" + @pytest.fixture(autouse=True) + def _mock_loop(self): + """Замокать tasks.loop, чтобы не создавать реальный coroutine.""" + with patch("utils.morning_runner.tasks.loop", return_value=MagicMock()): + yield + def test_start_starts_loop(self): """start() должен вызывать start() на loop.""" bot = AsyncMock() @@ -120,12 +138,18 @@ class TestRunMorning: channel.guild.me = MagicMock() channel.permissions_for.return_value.send_messages = True - with patch("utils.morning_runner.asyncio.gather", new=AsyncMock(return_value=( - {"current_condition": [{"temp_C": "20", "FeelsLikeC": "22", "weatherDesc": [{"value": "Clear"}], "humidity": "50", "windspeedKmph": "10", "pressure": "1013"}]}, - [{"title": "Test", "link": "http://test.com", "pub_date": "Mon, 01 Jan 2026 00:00:00 GMT", "creator": "", "tags": []}], - [{"title": "Test", "link": "http://test.com", "pub_date": "Mon, 01 Jan 2026 00:00:00 GMT", "creator": "", "tags": []}], - "http://cat.jpg", - ))), patch("utils.morning_runner.discord.Embed") as mock_embed: + weather_data = { + "current_condition": [ + {"temp_C": "20", "FeelsLikeC": "22", "weatherDesc": [{"value": "Clear"}], "humidity": "50", "windspeedKmph": "10", "pressure": "1013"} + ] + } + articles = [{"title": "Test", "link": "http://test.com", "pub_date": "Mon, 01 Jan 2026 00:00:00 GMT", "creator": "", "tags": []}] + posts = [{"title": "Test", "link": "http://test.com", "pub_date": "Mon, 01 Jan 2026 00:00:00 GMT", "creator": "", "tags": []}] + + with patch("utils.morning_runner.fetch_weather", new=AsyncMock(return_value=weather_data)), \ + patch("utils.morning_runner.fetch_rss", new=AsyncMock(side_effect=[articles, posts])), \ + patch("utils.morning_runner.fetch_cat", new=AsyncMock(return_value="http://cat.jpg")), \ + patch("utils.morning_runner.discord.Embed") as mock_embed: await run_morning(bot, channel) channel.send.assert_called_once()