"""Tests for HttpClientManager.""" import pytest from unittest.mock import MagicMock, AsyncMock, patch class TestHttpClientManager: """Tests for HTTP client pool management.""" @pytest.mark.unit def test_manager_initializes_with_settings(self): """Manager should initialize with config settings.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings( http_max_connections=50, http_connect_timeout=15.0, ) manager = HttpClientManager(settings) assert manager.max_connections == 50 assert manager.connect_timeout == 15.0 assert manager._default_client is None # Not started yet @pytest.mark.asyncio @pytest.mark.unit async def test_startup_creates_client(self): """Startup should create the default async client.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) await manager.startup() assert manager._default_client is not None await manager.shutdown() @pytest.mark.asyncio @pytest.mark.unit async def test_shutdown_closes_client(self): """Shutdown should close all clients gracefully.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) await manager.startup() client = manager._default_client await manager.shutdown() assert manager._default_client is None assert client.is_closed @pytest.mark.asyncio @pytest.mark.unit async def test_get_client_returns_default(self): """get_client() should return the default client.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) await manager.startup() client = manager.get_client() assert client is manager._default_client await manager.shutdown() @pytest.mark.asyncio @pytest.mark.unit async def test_get_client_raises_if_not_started(self): """get_client() should raise RuntimeError if manager not started.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) with pytest.raises(RuntimeError, match="not started"): manager.get_client() @pytest.mark.asyncio @pytest.mark.unit async def test_run_blocking_executes_in_thread_pool(self): """run_blocking should execute sync functions in thread pool.""" from app.http_client import HttpClientManager from app.config import Settings import threading settings = Settings() manager = HttpClientManager(settings) await manager.startup() main_thread = threading.current_thread() execution_thread = None def blocking_func(): nonlocal execution_thread execution_thread = threading.current_thread() return "result" result = await manager.run_blocking(blocking_func) assert result == "result" assert execution_thread is not main_thread await manager.shutdown() @pytest.mark.asyncio @pytest.mark.unit async def test_run_blocking_raises_if_not_started(self): """run_blocking should raise RuntimeError if manager not started.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) with pytest.raises(RuntimeError, match="not started"): await manager.run_blocking(lambda: None) @pytest.mark.asyncio @pytest.mark.unit async def test_startup_idempotent(self): """Calling startup multiple times should be safe.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) await manager.startup() client1 = manager._default_client await manager.startup() # Should not create a new client client2 = manager._default_client assert client1 is client2 # Same client instance await manager.shutdown() @pytest.mark.asyncio @pytest.mark.unit async def test_shutdown_idempotent(self): """Calling shutdown multiple times should be safe.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) await manager.startup() await manager.shutdown() await manager.shutdown() # Should not raise assert manager._default_client is None @pytest.mark.asyncio @pytest.mark.unit async def test_properties_return_configured_values(self): """Properties should return configured values.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings( http_max_connections=75, http_worker_threads=16, ) manager = HttpClientManager(settings) await manager.startup() assert manager.pool_size == 75 assert manager.executor_max == 16 await manager.shutdown() @pytest.mark.asyncio @pytest.mark.unit async def test_active_connections_when_not_started(self): """active_connections should return 0 when not started.""" from app.http_client import HttpClientManager from app.config import Settings settings = Settings() manager = HttpClientManager(settings) assert manager.active_connections == 0