"""포트폴리오 /api/portfolio 응답의 total_buy 계산 회귀 테스트 (CODE_REVIEW F4). purchase_price는 종목별 단가(1주당) 의미. total_buy = SUM(purchase_price × quantity). purchase_price가 없으면 avg_price로 폴백 후 동일하게 수량 곱산. """ from unittest.mock import patch from fastapi.testclient import TestClient from app.main import app def _fake_db_setup(monkeypatch, items, cash=None): from app import main as stock_main monkeypatch.setattr(stock_main, "get_all_portfolio", lambda: items) monkeypatch.setattr(stock_main, "get_all_broker_cash", lambda: cash or []) def test_portfolio_total_buy_uses_purchase_price_times_quantity(monkeypatch): """purchase_price 설정 시: total_buy = purchase_price × quantity 의 합.""" items = [ {"id": 1, "broker": "KB", "ticker": "005930", "name": "삼성전자", "quantity": 100, "avg_price": 72000, "purchase_price": 70000}, ] fake_prices = {"005930": {"price": 74500, "session": "REGULAR", "as_of": "2026-05-17T10:00:00+09:00"}} _fake_db_setup(monkeypatch, items) from app import main as stock_main monkeypatch.setattr(stock_main, "get_current_prices_detail", lambda t: fake_prices) client = TestClient(app) resp = client.get("/api/portfolio") assert resp.status_code == 200 data = resp.json() # purchase_price=70000 × quantity=100 = 7,000,000 assert data["summary"]["total_buy"] == 7_000_000 def test_portfolio_total_buy_falls_back_to_avg_price_with_quantity(monkeypatch): """purchase_price 미설정 시: avg_price 폴백 + 수량 곱산. API_SPEC 예시와 일치.""" items = [ {"id": 1, "broker": "KB", "ticker": "005930", "name": "삼성전자", "quantity": 100, "avg_price": 72000, "purchase_price": None}, ] fake_prices = {"005930": {"price": 74500, "session": "REGULAR", "as_of": "2026-05-17T10:00:00+09:00"}} _fake_db_setup(monkeypatch, items) from app import main as stock_main monkeypatch.setattr(stock_main, "get_current_prices_detail", lambda t: fake_prices) client = TestClient(app) resp = client.get("/api/portfolio") assert resp.status_code == 200 data = resp.json() # avg_price=72000 × quantity=100 = 7,200,000 (API_SPEC.md 예시와 일치) assert data["summary"]["total_buy"] == 7_200_000 def test_portfolio_total_buy_sums_multiple_holdings(monkeypatch): """여러 종목 합산도 단가 × 수량 합.""" items = [ {"id": 1, "broker": "KB", "ticker": "005930", "name": "삼성전자", "quantity": 100, "avg_price": 70000, "purchase_price": 70000}, {"id": 2, "broker": "NH", "ticker": "000660", "name": "SK하이닉스", "quantity": 50, "avg_price": 130000, "purchase_price": 130000}, ] fake_prices = { "005930": {"price": 74500, "session": "REGULAR", "as_of": "2026-05-17T10:00:00+09:00"}, "000660": {"price": 140000, "session": "REGULAR", "as_of": "2026-05-17T10:00:00+09:00"}, } _fake_db_setup(monkeypatch, items) from app import main as stock_main monkeypatch.setattr(stock_main, "get_current_prices_detail", lambda t: fake_prices) client = TestClient(app) resp = client.get("/api/portfolio") data = resp.json() # 70000*100 + 130000*50 = 7,000,000 + 6,500,000 = 13,500,000 assert data["summary"]["total_buy"] == 13_500_000