build 040: restore quote REST fallback after build 039

This commit is contained in:
2026-07-14 11:15:01 +03:00
parent 7b62873832
commit 9df9c0f5e0
4 changed files with 302 additions and 1 deletions

View File

@@ -9,6 +9,7 @@ from typing import cast
import pytest
import src.integrations.exchange.service as service_module
from src.core.config import Settings
from src.integrations.exchange.exceptions import ExchangeError
from src.integrations.exchange.market_cache import MarketPriceCache
@@ -116,3 +117,179 @@ def test_get_quote_wraps_acquisition_error(
service._get_fresh_quote("BTC/USD_LEVERAGE")
assert exc_info.value.__cause__ is original
def test_refresh_quote_cache_forces_fresh_quote_and_preserves_identity(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service()
cached = _quote()
fresh = _quote()
MarketPriceCache.set_quote(cached, runtime_key="auto")
requested_symbols: list[str] = []
monkeypatch.setattr(
service,
"validate_symbol",
lambda symbol: SimpleNamespace(
is_valid=True,
normalized_symbol=(requested_symbols.append(symbol) or fresh.symbol),
message="",
),
)
monkeypatch.setattr(service, "_get_fresh_quote", lambda _: fresh)
result = service.refresh_quote_cache(
" btc/usd_leverage ",
runtime_key="auto",
)
assert requested_symbols == [" btc/usd_leverage "]
assert result is fresh
assert result is not cached
assert MarketPriceCache.get_quote(fresh.symbol, runtime_key="auto") is fresh
def test_refresh_quote_cache_uses_default_runtime_key(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service()
fresh = _quote()
monkeypatch.setattr(
service,
"validate_symbol",
lambda _: SimpleNamespace(
is_valid=True,
normalized_symbol=fresh.symbol,
message="",
),
)
monkeypatch.setattr(service, "_get_fresh_quote", lambda _: fresh)
result = service.refresh_quote_cache(fresh.symbol)
assert result is fresh
assert MarketPriceCache.get_quote(fresh.symbol, runtime_key="auto") is fresh
def test_refresh_quote_cache_normalizes_runtime_key(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service()
fresh = _quote()
monkeypatch.setattr(
service,
"validate_symbol",
lambda _: SimpleNamespace(
is_valid=True,
normalized_symbol=fresh.symbol,
message="",
),
)
monkeypatch.setattr(service, "_get_fresh_quote", lambda _: fresh)
result = service.refresh_quote_cache(
fresh.symbol,
runtime_key=" Debug_Auto ",
)
assert result is fresh
assert (
MarketPriceCache.get_quote(
fresh.symbol,
runtime_key="debug_auto",
)
is fresh
)
def test_refresh_quote_cache_rejects_invalid_symbol(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service()
monkeypatch.setattr(
service,
"validate_symbol",
lambda _: SimpleNamespace(
is_valid=False,
normalized_symbol="UNKNOWN/USD",
message="Символ не найден.",
),
)
monkeypatch.setattr(
service,
"_get_fresh_quote",
lambda _: (_ for _ in ()).throw(
AssertionError("Fresh Quote must not be requested.")
),
)
with pytest.raises(ExchangeError, match="Символ не найден"):
service.refresh_quote_cache("UNKNOWN/USD", runtime_key="auto")
def test_refresh_quote_cache_does_not_update_cache_on_acquisition_error(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service()
cached = _quote()
original = RuntimeError("unavailable")
MarketPriceCache.set_quote(cached, runtime_key="auto")
monkeypatch.setattr(
service,
"validate_symbol",
lambda _: SimpleNamespace(
is_valid=True,
normalized_symbol=cached.symbol,
message="",
),
)
monkeypatch.setattr(
service,
"_load_quote_via_acquisition",
lambda _: (_ for _ in ()).throw(original),
)
monkeypatch.setattr(service, "_log_exchange_error", lambda **_: None)
with pytest.raises(ExchangeError) as exc_info:
service.refresh_quote_cache(cached.symbol, runtime_key="auto")
assert exc_info.value.__cause__ is original
assert MarketPriceCache.get_quote(cached.symbol, runtime_key="auto") is cached
def test_refresh_quote_cache_uses_and_stores_mock_quote(
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = _service(exchange_enabled=False)
mock = _quote()
monkeypatch.setattr(service_module, "mock_quote", lambda _: mock)
monkeypatch.setattr(
service,
"validate_symbol",
lambda _: (_ for _ in ()).throw(
AssertionError("Validation is not expected in mock mode.")
),
)
monkeypatch.setattr(
service,
"_get_fresh_quote",
lambda _: (_ for _ in ()).throw(
AssertionError("REST is not expected in mock mode.")
),
)
result = service.refresh_quote_cache(
"BTC/USD_LEVERAGE",
runtime_key="debug_auto",
)
assert result is mock
assert (
MarketPriceCache.get_quote(
mock.symbol,
runtime_key="debug_auto",
)
is mock
)