|
|
|
@ -246,8 +246,8 @@ class TestGetCachedData:
|
|
|
|
"AG2606", "futures", ["5min"], end_time=end_time, max_candles=50
|
|
|
|
"AG2606", "futures", ["5min"], end_time=end_time, max_candles=50
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def test_applies_end_time_and_max_candles_to_storage_results(self, db, storage_manager_mock):
|
|
|
|
def test_does_not_refilter_storage_manager_results(self, db, storage_manager_mock):
|
|
|
|
"""StorageManager 返回的数据会按 end_time / max_candles 过滤截断。"""
|
|
|
|
"""cache.py 不再对 StorageManager 返回的数据做二次过滤,直接原样返回。"""
|
|
|
|
fetched_at = datetime.now()
|
|
|
|
fetched_at = datetime.now()
|
|
|
|
|
|
|
|
|
|
|
|
def mock_get_market_data(symbol, data_type, periods, end_time=None, max_candles=100):
|
|
|
|
def mock_get_market_data(symbol, data_type, periods, end_time=None, max_candles=100):
|
|
|
|
@ -280,9 +280,40 @@ class TestGetCachedData:
|
|
|
|
|
|
|
|
|
|
|
|
assert result is not None
|
|
|
|
assert result is not None
|
|
|
|
candles = result["timeframes"]["5min"]
|
|
|
|
candles = result["timeframes"]["5min"]
|
|
|
|
# 过滤掉 10:05 之后保留 09:50/09:55,再截断为最新 1 条
|
|
|
|
# StorageManager 未做过滤,cache.py 也不应再次过滤
|
|
|
|
assert len(candles) == 1
|
|
|
|
assert len(candles) == 3
|
|
|
|
assert candles[0]["datetime"] == "2026-07-04T09:55:00"
|
|
|
|
|
|
|
|
|
|
|
|
def test_does_not_mutate_storage_manager_result(self, db, storage_manager_mock):
|
|
|
|
|
|
|
|
"""get_cached_data 返回 StorageManager 结果时不会原地修改原对象。"""
|
|
|
|
|
|
|
|
fetched_at = datetime.now()
|
|
|
|
|
|
|
|
original = {
|
|
|
|
|
|
|
|
"symbol": "AG2606",
|
|
|
|
|
|
|
|
"type": "futures",
|
|
|
|
|
|
|
|
"current_price": 123.45,
|
|
|
|
|
|
|
|
"timestamp": fetched_at.isoformat(),
|
|
|
|
|
|
|
|
"fetched_at": fetched_at.isoformat(),
|
|
|
|
|
|
|
|
"timeframes": {
|
|
|
|
|
|
|
|
"5min": [
|
|
|
|
|
|
|
|
{"datetime": "2026-07-04T09:55:00", "open": 100, "close": 110}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"is_fresh": True,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
storage_manager_mock.get_market_data.return_value = original
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with patch("app.services.cache.get_storage_manager", return_value=storage_manager_mock):
|
|
|
|
|
|
|
|
from app.services import cache
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = cache.get_cached_data(db, "AG2606", "futures", ["5min"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert result is not None
|
|
|
|
|
|
|
|
assert result is not original
|
|
|
|
|
|
|
|
assert result["timeframes"]["5min"] == original["timeframes"]["5min"]
|
|
|
|
|
|
|
|
# 修改返回结果不应影响 StorageManager 返回的原对象
|
|
|
|
|
|
|
|
result["timeframes"]["5min"].append(
|
|
|
|
|
|
|
|
{"datetime": "2026-07-04T10:00:00", "open": 111, "close": 112}
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
assert len(original["timeframes"]["5min"]) == 1
|
|
|
|
|
|
|
|
|
|
|
|
def test_queries_all_periods_when_periods_is_none(self, db, storage_manager_mock):
|
|
|
|
def test_queries_all_periods_when_periods_is_none(self, db, storage_manager_mock):
|
|
|
|
"""periods=None 时优先走 StorageManager 查询全部周期。"""
|
|
|
|
"""periods=None 时优先走 StorageManager 查询全部周期。"""
|
|
|
|
|