fork
This commit is contained in:
206
tests/test_subscription_service.py
Normal file
206
tests/test_subscription_service.py
Normal file
@@ -0,0 +1,206 @@
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from src.services import SubscriptionService
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_repo() -> MagicMock:
|
||||
repo = MagicMock()
|
||||
repo.subscribe_subject = MagicMock(return_value=True)
|
||||
repo.remove_subscription = MagicMock(return_value=True)
|
||||
repo.find_group_subscription_candidates = MagicMock(return_value=[])
|
||||
return repo
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_service() -> MagicMock:
|
||||
service = MagicMock()
|
||||
service.search_subjects = AsyncMock()
|
||||
service.get_subject_details = AsyncMock()
|
||||
service.get_calendar = AsyncMock()
|
||||
service.get_latest_episode = AsyncMock()
|
||||
service.get_subject_base64image = AsyncMock()
|
||||
return service
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subscribe_success(mock_repo, mock_service) -> None:
|
||||
mock_service.search_subjects.return_value = {"data": [{"id": 123}]}
|
||||
mock_service.get_subject_details.return_value = {
|
||||
"id": 123,
|
||||
"name": "Test Anime",
|
||||
"name_cn": "测试番剧",
|
||||
"date": "2024-01-01",
|
||||
"eps": 12,
|
||||
}
|
||||
mock_service.get_calendar.return_value = [{"items": [{"id": 123}]}]
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.subscribe("group_1", "Test Anime")
|
||||
|
||||
assert "成功订阅《测试番剧》" in result
|
||||
mock_repo.subscribe_subject.assert_called_once_with(
|
||||
group_id="group_1",
|
||||
subject_id="123",
|
||||
name="测试番剧",
|
||||
air_date="2024-01-01",
|
||||
total_episodes=12,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unsubscribe_local_single_match_success(mock_repo, mock_service) -> None:
|
||||
mock_repo.find_group_subscription_candidates.return_value = [
|
||||
SimpleNamespace(subject_id="123", name="测试番剧")
|
||||
]
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.unsubscribe("group_1", "测")
|
||||
|
||||
assert "已成功取消订阅《测试番剧》" in result
|
||||
mock_repo.find_group_subscription_candidates.assert_called_once_with(
|
||||
group_id="group_1", keyword="测", limit=6
|
||||
)
|
||||
mock_repo.remove_subscription.assert_called_once_with("group_1", "123")
|
||||
mock_service.search_subjects.assert_not_called()
|
||||
mock_service.get_subject_details.assert_not_called()
|
||||
mock_service.get_calendar.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unsubscribe_local_no_match(mock_repo, mock_service) -> None:
|
||||
mock_repo.find_group_subscription_candidates.return_value = []
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.unsubscribe("group_1", "不存在")
|
||||
|
||||
assert "未找到与「不存在」匹配的本群订阅番剧" in result
|
||||
mock_repo.remove_subscription.assert_not_called()
|
||||
mock_service.search_subjects.assert_not_called()
|
||||
mock_service.get_subject_details.assert_not_called()
|
||||
mock_service.get_calendar.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unsubscribe_local_multi_match_returns_candidates(
|
||||
mock_repo, mock_service
|
||||
) -> None:
|
||||
mock_repo.find_group_subscription_candidates.return_value = [
|
||||
SimpleNamespace(subject_id="1", name="进击的巨人"),
|
||||
SimpleNamespace(subject_id="2", name="进击!巨人中学"),
|
||||
SimpleNamespace(subject_id="3", name="巨人族的新娘"),
|
||||
]
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.unsubscribe("group_1", "巨人")
|
||||
|
||||
assert "匹配到多个已订阅番剧" in result
|
||||
assert "1. 进击的巨人 (ID: 1)" in result
|
||||
assert "2. 进击!巨人中学 (ID: 2)" in result
|
||||
assert "3. 巨人族的新娘 (ID: 3)" in result
|
||||
mock_repo.remove_subscription.assert_not_called()
|
||||
mock_service.search_subjects.assert_not_called()
|
||||
mock_service.get_subject_details.assert_not_called()
|
||||
mock_service.get_calendar.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unsubscribe_local_remove_failed(mock_repo, mock_service) -> None:
|
||||
mock_repo.find_group_subscription_candidates.return_value = [
|
||||
SimpleNamespace(subject_id="123", name="测试番剧")
|
||||
]
|
||||
mock_repo.remove_subscription.return_value = False
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.unsubscribe("group_1", "测")
|
||||
|
||||
assert "取消订阅失败:你可能并没有订阅《测试番剧》" in result
|
||||
mock_repo.remove_subscription.assert_called_once_with("group_1", "123")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_subscribe_candidates_multi_match(mock_repo, mock_service) -> None:
|
||||
mock_service.search_subjects.return_value = {
|
||||
"data": [
|
||||
{"id": 1, "name_cn": "进击的巨人"},
|
||||
{"id": 2, "name": "进击!巨人中学"},
|
||||
{"id": 1, "name_cn": "进击的巨人"},
|
||||
{"name_cn": "无ID条目"},
|
||||
]
|
||||
}
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
error_msg, candidates = await sub_service.get_subscribe_candidates("巨人", 5)
|
||||
|
||||
assert error_msg is None
|
||||
assert candidates == [
|
||||
{"subject_id": "1", "name": "进击的巨人"},
|
||||
{"subject_id": "2", "name": "进击!巨人中学"},
|
||||
]
|
||||
mock_service.search_subjects.assert_awaited_once_with(
|
||||
keyword="巨人",
|
||||
limit=5,
|
||||
subject_type=[2],
|
||||
subject_tags=None,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subscribe_by_subject_id_success(mock_repo, mock_service) -> None:
|
||||
mock_service.get_subject_details.return_value = {
|
||||
"id": 456,
|
||||
"name": "Test Name",
|
||||
"name_cn": "测试番剧2",
|
||||
"date": "2025-01-01",
|
||||
"eps": 24,
|
||||
}
|
||||
mock_service.get_calendar.return_value = [{"items": [{"id": 456}]}]
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.subscribe_by_subject_id("group_1", "456")
|
||||
|
||||
assert "✅ 成功订阅《测试番剧2》" in result
|
||||
mock_repo.subscribe_subject.assert_called_once_with(
|
||||
group_id="group_1",
|
||||
subject_id="456",
|
||||
name="测试番剧2",
|
||||
air_date="2025-01-01",
|
||||
total_episodes=24,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subscribe_by_subject_id_not_in_calendar(mock_repo, mock_service) -> None:
|
||||
mock_service.get_subject_details.return_value = {
|
||||
"id": 789,
|
||||
"name": "Not In Calendar",
|
||||
"name_cn": "未放送番剧",
|
||||
"date": "2025-06-01",
|
||||
"eps": 12,
|
||||
}
|
||||
mock_service.get_calendar.return_value = [{"items": [{"id": 456}]}]
|
||||
|
||||
sub_service = SubscriptionService(
|
||||
repository=mock_repo, service=mock_service, config_manager=MagicMock()
|
||||
)
|
||||
result = await sub_service.subscribe_by_subject_id("group_1", "789")
|
||||
|
||||
assert "不在当前的每日放送列表中" in result
|
||||
mock_repo.subscribe_subject.assert_not_called()
|
||||
Reference in New Issue
Block a user