fork
This commit is contained in:
107
tests/test_calendar_service.py
Normal file
107
tests/test_calendar_service.py
Normal file
@@ -0,0 +1,107 @@
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
import src.services.calendar as calendar_module
|
||||
from src.services import BangumiApiError, CalendarService
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def service() -> CalendarService:
|
||||
return CalendarService(access_token="token", user_agent="ua")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_cache_hit(service: CalendarService) -> None:
|
||||
payload = [{"weekday": {"id": 1}, "items": [{"id": 1, "name": "A"}]}]
|
||||
service._request = AsyncMock(return_value=payload)
|
||||
|
||||
first = await service.get_calendar()
|
||||
second = await service.get_calendar()
|
||||
|
||||
assert first == second
|
||||
assert service._request.await_count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_cache_expired_refresh(
|
||||
service: CalendarService, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
now = 1_000_000.0
|
||||
|
||||
def fake_time() -> float:
|
||||
return now
|
||||
|
||||
monkeypatch.setattr(calendar_module.time, "time", fake_time)
|
||||
|
||||
service._request = AsyncMock(
|
||||
side_effect=[
|
||||
[{"weekday": {"id": 1}, "items": []}],
|
||||
[{"weekday": {"id": 2}, "items": []}],
|
||||
]
|
||||
)
|
||||
|
||||
first = await service.get_calendar()
|
||||
now += service.CALENDAR_CACHE_TTL_SECONDS + 1
|
||||
second = await service.get_calendar()
|
||||
|
||||
assert first != second
|
||||
assert service._request.await_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_cache_returns_deepcopy(service: CalendarService) -> None:
|
||||
payload = [{"weekday": {"id": 1}, "items": []}]
|
||||
service._request = AsyncMock(return_value=payload)
|
||||
|
||||
first = await service.get_calendar()
|
||||
first[0]["weekday"]["id"] = 7
|
||||
second = await service.get_calendar()
|
||||
|
||||
assert second[0]["weekday"]["id"] == 1
|
||||
assert service._request.await_count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_cache_refresh_failed_fallback_stale(
|
||||
service: CalendarService, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
now = 2_000_000.0
|
||||
|
||||
def fake_time() -> float:
|
||||
return now
|
||||
|
||||
monkeypatch.setattr(calendar_module.time, "time", fake_time)
|
||||
|
||||
service._request = AsyncMock(
|
||||
side_effect=[
|
||||
[{"weekday": {"id": 1}, "items": [{"id": 1}]}],
|
||||
BangumiApiError("boom"),
|
||||
]
|
||||
)
|
||||
|
||||
first = await service.get_calendar()
|
||||
now += service.CALENDAR_CACHE_TTL_SECONDS + 1
|
||||
second = await service.get_calendar()
|
||||
|
||||
assert second == first
|
||||
assert service._request.await_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_cache_concurrent_single_refresh(
|
||||
service: CalendarService,
|
||||
) -> None:
|
||||
payload = [{"weekday": {"id": 3}, "items": []}]
|
||||
|
||||
async def slow_fetch(*args: object, **kwargs: object) -> list[dict[str, object]]:
|
||||
await asyncio.sleep(0.05)
|
||||
return payload
|
||||
|
||||
service._request = AsyncMock(side_effect=slow_fetch)
|
||||
|
||||
first, second = await asyncio.gather(service.get_calendar(), service.get_calendar())
|
||||
|
||||
assert first == second
|
||||
assert service._request.await_count == 1
|
||||
Reference in New Issue
Block a user