from unittest.mock import AsyncMock, MagicMock import pytest from astrbot.api.event import AstrMessageEvent from src.services import SearchService @pytest.fixture def mock_service() -> MagicMock: service = MagicMock() service.search_subjects = AsyncMock() service.get_subject_details = AsyncMock() service.get_subject_episodes = AsyncMock() service.get_calendar = AsyncMock() return service @pytest.fixture def mock_config_manager() -> MagicMock: config_manager = MagicMock() config_manager.get_render_server_url.return_value = "https://api.unitedpooh.top/rpc" config_manager.get_max_retries.return_value = 1 return config_manager @pytest.mark.asyncio async def test_handle_calendar_success( mock_service: MagicMock, mock_config_manager: MagicMock ) -> None: # 准备 Mock 数据 mock_service.get_calendar.return_value = [{"weekday": {"id": 1}, "items": []}] search_service = SearchService( service=mock_service, config_manager=mock_config_manager ) # Mock 渲染器,避免进入模板渲染逻辑 search_service.calendar_renderer.render_calendar = AsyncMock( return_value="fake_base64" ) event = MagicMock(spec=AstrMessageEvent) event.chain_result = MagicMock(side_effect=lambda x: x) results: list[object] = [] async for res in search_service.handle_calendar(event): results.append(res) assert len(results) > 0 mock_service.get_calendar.assert_called_once() event.chain_result.assert_called_once() @pytest.mark.asyncio async def test_handle_subject_search_no_query( mock_service: MagicMock, mock_config_manager: MagicMock ) -> None: search_service = SearchService( service=mock_service, config_manager=mock_config_manager ) event = MagicMock(spec=AstrMessageEvent) event.plain_result = MagicMock(side_effect=lambda x: x) results: list[object] = [] async for res in search_service.handle_subject_search(event, query=""): results.append(res) assert len(results) > 0 assert "❌ 请提供搜索关键词" in str(results[0])