"""Tests for OpenAPI partial-data fallback in price collectors.""" from datetime import date from unittest.mock import patch from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool from app.core.database import Base from app.models.stock import AssetClass, ETF, Price, Stock from app.services.collectors.etf_price_collector import ETFPriceCollector from app.services.collectors.price_collector import PriceCollector def make_db(): engine = create_engine( "sqlite:///:memory:", connect_args={"check_same_thread": False}, poolclass=StaticPool, ) Base.metadata.create_all(bind=engine) Session = sessionmaker(bind=engine) session = Session() return session, engine def test_price_collector_falls_back_when_openapi_misses_end_date(): db, engine = make_db() try: db.add( Stock( ticker="005930", name="Samsung Electronics", market="KOSPI", base_date=date(2026, 5, 15), ) ) db.add( Price( ticker="005930", date=date(2026, 5, 14), open=70000, high=71000, low=69000, close=70500, volume=1000, ) ) db.commit() with patch("app.services.collectors.price_collector.get_krx_client", return_value=object()), \ patch.object(PriceCollector, "_collect_openapi", return_value=1), \ patch.object(PriceCollector, "_collect_pykrx", return_value=1) as mock_pykrx: total = PriceCollector(db, start_date="20260514", end_date="20260515").collect() assert total == 1 mock_pykrx.assert_called_once() finally: db.close() Base.metadata.drop_all(bind=engine) def test_price_collector_skips_fallback_when_openapi_has_end_date(): db, engine = make_db() try: db.add( Stock( ticker="005930", name="Samsung Electronics", market="KOSPI", base_date=date(2026, 5, 15), ) ) db.add( Price( ticker="005930", date=date(2026, 5, 15), open=70000, high=71000, low=69000, close=70500, volume=1000, ) ) db.commit() with patch("app.services.collectors.price_collector.get_krx_client", return_value=object()), \ patch.object(PriceCollector, "_collect_openapi", return_value=1), \ patch.object(PriceCollector, "_collect_pykrx", return_value=1) as mock_pykrx: total = PriceCollector(db, start_date="20260514", end_date="20260515").collect() assert total == 1 mock_pykrx.assert_not_called() finally: db.close() Base.metadata.drop_all(bind=engine) def test_etf_price_collector_falls_back_when_openapi_returns_zero(): db, engine = make_db() try: db.add( ETF( ticker="069500", name="KODEX 200", asset_class=AssetClass.EQUITY, market="KOSPI", ) ) db.commit() with patch("app.services.collectors.etf_price_collector.get_krx_client", return_value=object()), \ patch.object(ETFPriceCollector, "_collect_openapi", return_value=0), \ patch.object(ETFPriceCollector, "_collect_pykrx", return_value=1) as mock_pykrx: total = ETFPriceCollector(db, start_date="20260515", end_date="20260515").collect() assert total == 1 mock_pykrx.assert_called_once() finally: db.close() Base.metadata.drop_all(bind=engine)