167 lines
3.8 KiB
Python
167 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
import src.bootstrap.app_factory as app_factory
|
|
from src.bootstrap.application import ApplicationComposition
|
|
|
|
|
|
class RecordingJournal:
|
|
def __init__(self) -> None:
|
|
self.info_calls: list[
|
|
tuple[str, str, dict[str, object]]
|
|
] = []
|
|
|
|
def log_info(
|
|
self,
|
|
event: str,
|
|
message: str,
|
|
context: dict[str, object],
|
|
) -> None:
|
|
self.info_calls.append(
|
|
(
|
|
event,
|
|
message,
|
|
context,
|
|
)
|
|
)
|
|
|
|
def log_critical(
|
|
self,
|
|
event: str,
|
|
message: str,
|
|
context: dict[str, object],
|
|
) -> None:
|
|
del event, message, context
|
|
|
|
|
|
def make_settings() -> SimpleNamespace:
|
|
return SimpleNamespace(
|
|
bot_token="test-token",
|
|
bot_parse_mode="HTML",
|
|
log_level="INFO",
|
|
app_env="test",
|
|
exchange_name="dzengi",
|
|
default_symbol="BTC/USD_LEVERAGE",
|
|
trade_stream=SimpleNamespace(enabled=True),
|
|
)
|
|
|
|
|
|
def test_create_app_builds_one_application_composition(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
settings = make_settings()
|
|
bot = object()
|
|
dispatcher = object()
|
|
runtime = object()
|
|
journal = RecordingJournal()
|
|
observed_runtime_settings: list[object] = []
|
|
registered_bots: list[object] = []
|
|
routed_dispatchers: list[object] = []
|
|
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"load_settings",
|
|
lambda: settings,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"setup_logging",
|
|
lambda level: None,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"init_schema",
|
|
lambda: None,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"JournalService",
|
|
lambda: journal,
|
|
)
|
|
|
|
def build_runtime(received_settings: object) -> object:
|
|
observed_runtime_settings.append(received_settings)
|
|
return runtime
|
|
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"build_trade_stream_production_runtime",
|
|
build_runtime,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"Bot",
|
|
lambda **kwargs: bot,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"Dispatcher",
|
|
lambda: dispatcher,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory.NotificationTargetRegistry,
|
|
"set_bot",
|
|
registered_bots.append,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"setup_routers",
|
|
routed_dispatchers.append,
|
|
)
|
|
|
|
application = app_factory.create_app()
|
|
|
|
assert isinstance(application, ApplicationComposition)
|
|
assert application.bot is bot
|
|
assert application.dispatcher is dispatcher
|
|
assert application.trade_stream_runtime is runtime
|
|
assert observed_runtime_settings == [settings]
|
|
assert registered_bots == [bot]
|
|
assert routed_dispatchers == [dispatcher]
|
|
assert journal.info_calls[0][2]["trade_stream_enabled"] is True
|
|
|
|
|
|
def test_runtime_build_error_is_fatal(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
expected = RuntimeError("invalid Trade Stream settings")
|
|
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"load_settings",
|
|
make_settings,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"setup_logging",
|
|
lambda level: None,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"init_schema",
|
|
lambda: None,
|
|
)
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"JournalService",
|
|
RecordingJournal,
|
|
)
|
|
|
|
def fail_runtime_build(settings: object) -> None:
|
|
del settings
|
|
raise expected
|
|
|
|
monkeypatch.setattr(
|
|
app_factory,
|
|
"build_trade_stream_production_runtime",
|
|
fail_runtime_build,
|
|
)
|
|
|
|
with pytest.raises(RuntimeError) as exc_info:
|
|
app_factory.create_app()
|
|
|
|
assert exc_info.value is expected
|