mirror of
https://github.com/shy3130/tick-stock-panel.git
synced 2026-11-02 10:26:13 +00:00
113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
"""扩展数据拉取的每配置超时 (PullConfig.timeout_seconds)。
|
|
|
|
历史行为是三处硬编码 30s: 大响应接口 (如全量集合竞价 /day, 实测 ~77s) 会超时。
|
|
现在超时进配置, 默认 30 与旧行为完全一致; 拉取 (_request_json) 与
|
|
URL 探测 (detect-url) 都读它。老 config.json 无该字段 → 默认 30, 手改非法值 → 归一 30。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from app.services import ext_pull
|
|
from app.services.ext_data import PullConfig
|
|
|
|
# ── 模型: 默认值 / 序列化 / 非法值归一 ──────────────────────────────
|
|
|
|
def test_timeout_defaults_to_30_and_roundtrips():
|
|
assert PullConfig().timeout_seconds == 30
|
|
assert PullConfig(timeout_seconds=90).timeout_seconds == 90
|
|
|
|
d = PullConfig(url="https://x", timeout_seconds=120).to_dict()
|
|
assert d["timeout_seconds"] == 120
|
|
assert PullConfig.from_dict(d).timeout_seconds == 120
|
|
|
|
|
|
def test_timeout_missing_in_old_config_falls_back_to_30():
|
|
legacy = PullConfig(url="https://x").to_dict()
|
|
del legacy["timeout_seconds"] # 模拟旧版本 config.json
|
|
assert PullConfig.from_dict(legacy).timeout_seconds == 30
|
|
|
|
|
|
@pytest.mark.parametrize("bad", [0, -5, 3, 301, 9999, "abc", None])
|
|
def test_timeout_invalid_values_normalized_to_30(bad):
|
|
assert PullConfig(timeout_seconds=bad).timeout_seconds == 30
|
|
|
|
|
|
# ── 拉取路径: _request_json 把配置超时传给 httpx ─────────────────────
|
|
|
|
class _FakeResponse:
|
|
def raise_for_status(self):
|
|
pass
|
|
|
|
def json(self):
|
|
return {"items": [{"symbol": "600000.SH"}]}
|
|
|
|
|
|
class _FakeClient:
|
|
"""捕获每次请求的 timeout。"""
|
|
|
|
last_timeout: object = None
|
|
request_timeout: object = None
|
|
|
|
def __init__(self, timeout=None, **kwargs):
|
|
_FakeClient.last_timeout = timeout
|
|
|
|
async def __aenter__(self):
|
|
return self
|
|
|
|
async def __aexit__(self, *exc):
|
|
return False
|
|
|
|
async def request(self, method, url, **kwargs):
|
|
_FakeClient.request_timeout = kwargs.get("timeout")
|
|
return _FakeResponse()
|
|
|
|
|
|
async def test_request_json_uses_configured_timeout(monkeypatch):
|
|
monkeypatch.setattr(ext_pull.httpx, "AsyncClient", _FakeClient)
|
|
|
|
pull = PullConfig(url="https://x", timeout_seconds=90)
|
|
await ext_pull._request_json(pull, "cfg1")
|
|
assert _FakeClient.request_timeout == 90
|
|
|
|
|
|
async def test_request_json_defaults_to_30_without_attr(monkeypatch):
|
|
monkeypatch.setattr(ext_pull.httpx, "AsyncClient", _FakeClient)
|
|
|
|
# 测试用的简化 pull 对象没有 timeout_seconds 属性 → 兜底 30
|
|
pull = SimpleNamespace(
|
|
url="https://x", date_param=None, date_format="iso", headers=None,
|
|
method="GET", body=None, auth=None,
|
|
)
|
|
await ext_pull._request_json(pull, "cfg1")
|
|
assert _FakeClient.request_timeout == 30
|
|
|
|
|
|
# ── 探测路径: detect-url 请求体带 timeout_seconds ───────────────────
|
|
|
|
async def test_detect_url_uses_request_timeout(monkeypatch):
|
|
import httpx
|
|
|
|
from app.api import ext_data as ext_api
|
|
|
|
monkeypatch.setattr(httpx, "AsyncClient", _FakeClient)
|
|
|
|
resp = await ext_api.detect_url(ext_api.DetectUrlReq(
|
|
url="https://x", response_path="items", timeout_seconds=120,
|
|
))
|
|
assert _FakeClient.last_timeout == 120
|
|
assert resp["status"] == "ok"
|
|
|
|
|
|
async def test_detect_url_timeout_defaults_to_30(monkeypatch):
|
|
import httpx
|
|
|
|
from app.api import ext_data as ext_api
|
|
|
|
monkeypatch.setattr(httpx, "AsyncClient", _FakeClient)
|
|
|
|
await ext_api.detect_url(ext_api.DetectUrlReq(url="https://x", response_path="items"))
|
|
assert _FakeClient.last_timeout == 30
|