from datetime import datetime, timedelta, timezone from common.enums import ErrorType from services.external.open_meteo import OpenMeteoRequestFailed WEATHER = { "temperature": 24.3, "weather_code": 1, "wind_speed": 3.2, "observed_at": "2026-08-27T14:00", "timezone": "Asia/Seoul", "latitude": 33.46, "longitude": 126.31, } async def test_weather_uses_region_cache(client, monkeypatch): calls = 0 async def fetch(_lat, _lon): nonlocal calls calls += 1 return WEATHER monkeypatch.setattr("services.local_content_service.fetch_current_weather", fetch) params = {"region_code": "50110253", "latitude": 33.46, "longitude": 126.31} first = (await client.get("/v1/local/weather", params=params)).json() second = (await client.get("/v1/local/weather", params=params)).json() assert first["weather"]["temperature"] == 24.3 assert first["cached"] is False assert second["cached"] is True assert calls == 1 async def test_weather_returns_stale_cache_when_upstream_fails(client, db_engine, monkeypatch): params = {"region_code": "50110253", "latitude": 33.46, "longitude": 126.31} monkeypatch.setattr("services.local_content_service.fetch_current_weather", lambda *_: _async_value(WEATHER)) await client.get("/v1/local/weather", params=params) async with db_engine.begin() as conn: from sqlalchemy import text await conn.execute(text("UPDATE area_contents SET expires_at = :expired"), { "expired": datetime.now(timezone.utc) - timedelta(minutes=1) }) async def fail(*_args): raise OpenMeteoRequestFailed("fail") monkeypatch.setattr("services.local_content_service.fetch_current_weather", fail) body = (await client.get("/v1/local/weather", params=params)).json() assert body["result"]["code"] == ErrorType.SUCCESS.value assert body["cached"] is True assert body["stale"] is True assert body["weather"]["temperature"] == 24.3 async def _async_value(value): return value