|
|
|
|
@ -2,7 +2,7 @@ import importlib
|
|
|
|
|
import json
|
|
|
|
|
import logging
|
|
|
|
|
import time
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
@ -348,6 +348,57 @@ class TestStorageManagerReadLogic:
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_is_fresh_true_within_cache_ttl(self):
|
|
|
|
|
"""数据在 CACHE_TTL_SECONDS(默认 300 秒)内时 is_fresh 为 True。"""
|
|
|
|
|
manager = StorageManager(redis_client=None, mysql_engine=None)
|
|
|
|
|
fetched_at = datetime(2026, 7, 4, 10, 0, 0)
|
|
|
|
|
now = fetched_at + timedelta(seconds=60)
|
|
|
|
|
|
|
|
|
|
mock_datetime = MagicMock()
|
|
|
|
|
mock_datetime.now.return_value = now
|
|
|
|
|
mock_datetime.fromisoformat = datetime.fromisoformat
|
|
|
|
|
|
|
|
|
|
with patch("app.storage_manager.datetime", mock_datetime):
|
|
|
|
|
result = manager._merge_period_results(
|
|
|
|
|
"AG2606",
|
|
|
|
|
"futures",
|
|
|
|
|
{
|
|
|
|
|
"5min": {
|
|
|
|
|
"current_price": 123.45,
|
|
|
|
|
"timestamp": fetched_at.isoformat(),
|
|
|
|
|
"candles": [],
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert result["is_fresh"] is True
|
|
|
|
|
|
|
|
|
|
def test_is_fresh_false_beyond_cache_ttl(self):
|
|
|
|
|
"""数据超过 CACHE_TTL_SECONDS(默认 300 秒)时 is_fresh 为 False。"""
|
|
|
|
|
manager = StorageManager(redis_client=None, mysql_engine=None)
|
|
|
|
|
fetched_at = datetime(2026, 7, 4, 10, 0, 0)
|
|
|
|
|
now = fetched_at + timedelta(seconds=301)
|
|
|
|
|
|
|
|
|
|
mock_datetime = MagicMock()
|
|
|
|
|
mock_datetime.now.return_value = now
|
|
|
|
|
mock_datetime.fromisoformat = datetime.fromisoformat
|
|
|
|
|
|
|
|
|
|
with patch("app.storage_manager.datetime", mock_datetime):
|
|
|
|
|
result = manager._merge_period_results(
|
|
|
|
|
"AG2606",
|
|
|
|
|
"futures",
|
|
|
|
|
{
|
|
|
|
|
"5min": {
|
|
|
|
|
"current_price": 123.45,
|
|
|
|
|
"timestamp": fetched_at.isoformat(),
|
|
|
|
|
"candles": [],
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert result["is_fresh"] is False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestStorageManagerWriteLogic:
|
|
|
|
|
"""StorageManager 双写一致性测试。"""
|
|
|
|
|
|
|
|
|
|
@ -792,18 +843,22 @@ class TestStorageManagerConfig:
|
|
|
|
|
"""配置读取相关测试。"""
|
|
|
|
|
|
|
|
|
|
def test_redis_ttl_reads_config_value(self):
|
|
|
|
|
"""StorageManager 应读取 app.config.REDIS_TTL_SECONDS 作为默认 TTL。"""
|
|
|
|
|
"""StorageManager 应分别读取 app.config.REDIS_TTL_SECONDS 与 CACHE_TTL_SECONDS。"""
|
|
|
|
|
import app.config as config
|
|
|
|
|
import app.storage_manager as sm
|
|
|
|
|
|
|
|
|
|
original_ttl = config.REDIS_TTL_SECONDS
|
|
|
|
|
original_redis_ttl = config.REDIS_TTL_SECONDS
|
|
|
|
|
original_cache_ttl = config.CACHE_TTL_SECONDS
|
|
|
|
|
original_singleton = sm._storage_manager
|
|
|
|
|
config.REDIS_TTL_SECONDS = 1234
|
|
|
|
|
config.CACHE_TTL_SECONDS = 5678
|
|
|
|
|
try:
|
|
|
|
|
importlib.reload(sm)
|
|
|
|
|
assert sm.CACHE_TTL_SECONDS == 1234
|
|
|
|
|
assert sm.REDIS_TTL_SECONDS == 1234
|
|
|
|
|
assert sm.CACHE_TTL_SECONDS == 5678
|
|
|
|
|
finally:
|
|
|
|
|
config.REDIS_TTL_SECONDS = original_ttl
|
|
|
|
|
config.REDIS_TTL_SECONDS = original_redis_ttl
|
|
|
|
|
config.CACHE_TTL_SECONDS = original_cache_ttl
|
|
|
|
|
importlib.reload(sm)
|
|
|
|
|
sm._storage_manager = original_singleton
|
|
|
|
|
|
|
|
|
|
|