test: add 159 tests for all new modules
New test files (171 tests): - test_routes_shorts.py (16) - short volume, FTD, interest, darkpool - test_routes_fixed_income.py (34) - treasury, yield curve, SOFR, etc. - test_routes_economy.py (44) - CPI, GDP, FRED search, Fed holdings - test_routes_surveys.py (17) - Michigan, SLOOS, NFP, Empire State - test_routes_regulators.py (20) - COT, SEC litigation, institutions - test_finnhub_service_social.py (20) - social/reddit sentiment unit tests - test_routes_sentiment_social.py (20) - social endpoints + composite Updated: - test_routes_sentiment.py - match new composite sentiment response shape Total: 261 tests passing (was 102)
This commit is contained in:
189
tests/test_routes_surveys.py
Normal file
189
tests/test_routes_surveys.py
Normal file
@@ -0,0 +1,189 @@
|
||||
"""Tests for economy survey routes."""
|
||||
|
||||
from unittest.mock import patch, AsyncMock
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient, ASGITransport
|
||||
|
||||
from main import app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client():
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as c:
|
||||
yield c
|
||||
|
||||
|
||||
# --- Michigan Consumer Sentiment ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock)
|
||||
async def test_survey_michigan_happy_path(mock_fn, client):
|
||||
mock_fn.return_value = [
|
||||
{"date": "2026-03-01", "consumer_sentiment": 76.5, "inflation_expectation_1yr": 3.1}
|
||||
]
|
||||
resp = await client.get("/api/v1/economy/surveys/michigan")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["success"] is True
|
||||
assert data["data"][0]["consumer_sentiment"] == 76.5
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock)
|
||||
async def test_survey_michigan_empty(mock_fn, client):
|
||||
mock_fn.return_value = []
|
||||
resp = await client.get("/api/v1/economy/surveys/michigan")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["data"] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_michigan", new_callable=AsyncMock)
|
||||
async def test_survey_michigan_service_error_returns_502(mock_fn, client):
|
||||
mock_fn.side_effect = RuntimeError("FRED unavailable")
|
||||
resp = await client.get("/api/v1/economy/surveys/michigan")
|
||||
assert resp.status_code == 502
|
||||
|
||||
|
||||
# --- SLOOS ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock)
|
||||
async def test_survey_sloos_happy_path(mock_fn, client):
|
||||
mock_fn.return_value = [
|
||||
{"date": "2026-01-01", "c_i_tightening_pct": 25.0, "consumer_tightening_pct": 10.0}
|
||||
]
|
||||
resp = await client.get("/api/v1/economy/surveys/sloos")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["success"] is True
|
||||
assert data["data"][0]["c_i_tightening_pct"] == 25.0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock)
|
||||
async def test_survey_sloos_empty(mock_fn, client):
|
||||
mock_fn.return_value = []
|
||||
resp = await client.get("/api/v1/economy/surveys/sloos")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["data"] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_sloos", new_callable=AsyncMock)
|
||||
async def test_survey_sloos_service_error_returns_502(mock_fn, client):
|
||||
mock_fn.side_effect = RuntimeError("FRED down")
|
||||
resp = await client.get("/api/v1/economy/surveys/sloos")
|
||||
assert resp.status_code == 502
|
||||
|
||||
|
||||
# --- Nonfarm Payrolls ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock)
|
||||
async def test_survey_nfp_happy_path(mock_fn, client):
|
||||
mock_fn.return_value = [
|
||||
{"date": "2026-03-07", "value": 275000, "industry": "total_nonfarm"}
|
||||
]
|
||||
resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["success"] is True
|
||||
assert data["data"][0]["value"] == 275000
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock)
|
||||
async def test_survey_nfp_empty(mock_fn, client):
|
||||
mock_fn.return_value = []
|
||||
resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["data"] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_nonfarm_payrolls", new_callable=AsyncMock)
|
||||
async def test_survey_nfp_service_error_returns_502(mock_fn, client):
|
||||
mock_fn.side_effect = RuntimeError("BLS unavailable")
|
||||
resp = await client.get("/api/v1/economy/surveys/nonfarm-payrolls")
|
||||
assert resp.status_code == 502
|
||||
|
||||
|
||||
# --- Empire State Manufacturing ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock)
|
||||
async def test_survey_empire_state_happy_path(mock_fn, client):
|
||||
mock_fn.return_value = [
|
||||
{"date": "2026-03-01", "general_business_conditions": -7.58}
|
||||
]
|
||||
resp = await client.get("/api/v1/economy/surveys/empire-state")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["success"] is True
|
||||
assert data["data"][0]["general_business_conditions"] == -7.58
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock)
|
||||
async def test_survey_empire_state_empty(mock_fn, client):
|
||||
mock_fn.return_value = []
|
||||
resp = await client.get("/api/v1/economy/surveys/empire-state")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["data"] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.get_empire_state", new_callable=AsyncMock)
|
||||
async def test_survey_empire_state_service_error_returns_502(mock_fn, client):
|
||||
mock_fn.side_effect = RuntimeError("FRED connection error")
|
||||
resp = await client.get("/api/v1/economy/surveys/empire-state")
|
||||
assert resp.status_code == 502
|
||||
|
||||
|
||||
# --- BLS Search ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock)
|
||||
async def test_survey_bls_search_happy_path(mock_fn, client):
|
||||
mock_fn.return_value = [
|
||||
{"series_id": "CES0000000001", "series_title": "All employees, thousands, total nonfarm"},
|
||||
{"series_id": "CES1000000001", "series_title": "All employees, thousands, mining and logging"},
|
||||
]
|
||||
resp = await client.get("/api/v1/economy/surveys/bls-search?query=nonfarm+payrolls")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["success"] is True
|
||||
assert len(data["data"]) == 2
|
||||
assert data["data"][0]["series_id"] == "CES0000000001"
|
||||
mock_fn.assert_called_once_with(query="nonfarm payrolls")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_survey_bls_search_missing_query(client):
|
||||
resp = await client.get("/api/v1/economy/surveys/bls-search")
|
||||
assert resp.status_code == 422
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock)
|
||||
async def test_survey_bls_search_empty(mock_fn, client):
|
||||
mock_fn.return_value = []
|
||||
resp = await client.get("/api/v1/economy/surveys/bls-search?query=nothingtofind")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["data"] == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("routes_surveys.surveys_service.bls_search", new_callable=AsyncMock)
|
||||
async def test_survey_bls_search_service_error_returns_502(mock_fn, client):
|
||||
mock_fn.side_effect = RuntimeError("BLS API down")
|
||||
resp = await client.get("/api/v1/economy/surveys/bls-search?query=wages")
|
||||
assert resp.status_code == 502
|
||||
Reference in New Issue
Block a user