60 lines
2.6 KiB
Python
60 lines
2.6 KiB
Python
|
|
"""
|
||
|
|
Tests for collection job orchestration.
|
||
|
|
"""
|
||
|
|
from unittest.mock import patch, MagicMock
|
||
|
|
|
||
|
|
from jobs.collection_job import run_daily_collection
|
||
|
|
|
||
|
|
|
||
|
|
def test_run_daily_collection_calls_collectors_in_order():
|
||
|
|
"""Daily collection should run all collectors in dependency order."""
|
||
|
|
call_order = []
|
||
|
|
|
||
|
|
def make_mock_collector(name):
|
||
|
|
mock_cls = MagicMock()
|
||
|
|
instance = MagicMock()
|
||
|
|
instance.run.side_effect = lambda: call_order.append(name)
|
||
|
|
mock_cls.return_value = instance
|
||
|
|
return mock_cls
|
||
|
|
|
||
|
|
with patch("jobs.collection_job.SessionLocal") as mock_session_local, \
|
||
|
|
patch("jobs.collection_job.StockCollector", make_mock_collector("stock")), \
|
||
|
|
patch("jobs.collection_job.SectorCollector", make_mock_collector("sector")), \
|
||
|
|
patch("jobs.collection_job.PriceCollector", make_mock_collector("price")), \
|
||
|
|
patch("jobs.collection_job.ValuationCollector", make_mock_collector("valuation")), \
|
||
|
|
patch("jobs.collection_job.ETFCollector", make_mock_collector("etf")), \
|
||
|
|
patch("jobs.collection_job.ETFPriceCollector", make_mock_collector("etf_price")):
|
||
|
|
mock_session_local.return_value = MagicMock()
|
||
|
|
run_daily_collection()
|
||
|
|
|
||
|
|
assert call_order == ["stock", "sector", "price", "valuation", "etf", "etf_price"]
|
||
|
|
|
||
|
|
|
||
|
|
def test_run_daily_collection_continues_on_failure():
|
||
|
|
"""If one collector fails, the rest should still run."""
|
||
|
|
call_order = []
|
||
|
|
|
||
|
|
def make_mock_collector(name, should_fail=False):
|
||
|
|
mock_cls = MagicMock()
|
||
|
|
instance = MagicMock()
|
||
|
|
def side_effect():
|
||
|
|
if should_fail:
|
||
|
|
raise RuntimeError(f"{name} failed")
|
||
|
|
call_order.append(name)
|
||
|
|
instance.run.side_effect = side_effect
|
||
|
|
mock_cls.return_value = instance
|
||
|
|
return mock_cls
|
||
|
|
|
||
|
|
with patch("jobs.collection_job.SessionLocal") as mock_session_local, \
|
||
|
|
patch("jobs.collection_job.StockCollector", make_mock_collector("stock", should_fail=True)), \
|
||
|
|
patch("jobs.collection_job.SectorCollector", make_mock_collector("sector")), \
|
||
|
|
patch("jobs.collection_job.PriceCollector", make_mock_collector("price")), \
|
||
|
|
patch("jobs.collection_job.ValuationCollector", make_mock_collector("valuation")), \
|
||
|
|
patch("jobs.collection_job.ETFCollector", make_mock_collector("etf")), \
|
||
|
|
patch("jobs.collection_job.ETFPriceCollector", make_mock_collector("etf_price")):
|
||
|
|
mock_session_local.return_value = MagicMock()
|
||
|
|
run_daily_collection()
|
||
|
|
|
||
|
|
# stock failed, but rest should continue
|
||
|
|
assert call_order == ["sector", "price", "valuation", "etf", "etf_price"]
|