43bc58770d
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
247 lines
9.5 KiB
Python
247 lines
9.5 KiB
Python
"""Comprehensive unit tests for app/api/openai.py module."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestOpenAITestConnection:
|
|
"""Tests for GET /openai/test endpoint."""
|
|
|
|
def test_openai_connection_success(self):
|
|
"""Test successful OpenAI API connection."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
# Mock the OpenAI client and models response
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock()
|
|
mock_models.data = [{"id": "gpt-4"}, {"id": "gpt-3.5-turbo"}]
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should return success status
|
|
# Should show number of available models
|
|
pass
|
|
|
|
def test_openai_connection_no_api_key(self):
|
|
"""Test connection when no API key is configured."""
|
|
from app.config import settings
|
|
|
|
with patch.object(settings, "openai_api_key", None):
|
|
# Should return error status
|
|
# Should indicate no API key configured
|
|
pass
|
|
|
|
def test_openai_connection_empty_api_key(self):
|
|
"""Test connection with empty API key."""
|
|
from app.config import settings
|
|
|
|
with patch.object(settings, "openai_api_key", ""):
|
|
# Should return error status
|
|
pass
|
|
|
|
def test_openai_connection_invalid_key(self):
|
|
"""Test connection with invalid API key."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("Invalid API key")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-invalid-key"):
|
|
# Should return error status
|
|
# Should indicate authentication error
|
|
pass
|
|
|
|
def test_openai_connection_authentication_error(self):
|
|
"""Test connection with authentication error."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("Authentication failed")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should return error status
|
|
# is_auth_error should be True
|
|
pass
|
|
|
|
def test_openai_connection_network_error(self):
|
|
"""Test connection with network error."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("Connection timeout")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should return error status
|
|
# Should include error details
|
|
pass
|
|
|
|
def test_openai_connection_models_without_data_attr(self):
|
|
"""Test handling of models response without data attribute."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock(spec=[]) # No 'data' attribute
|
|
del mock_models.data
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should return success
|
|
# models_available should be "Unknown"
|
|
pass
|
|
|
|
def test_openai_connection_import_error(self):
|
|
"""Test handling when OpenAI package is not installed."""
|
|
with patch.dict("sys.modules", {"openai": None}):
|
|
# Should return error status
|
|
# Should indicate OpenAI package not installed
|
|
pass
|
|
|
|
def test_openai_connection_unexpected_error(self):
|
|
"""Test handling of unexpected errors."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_openai_class.side_effect = RuntimeError("Unexpected error")
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should return error status
|
|
# Should include error details
|
|
pass
|
|
|
|
def test_openai_connection_logs_success(self):
|
|
"""Test that successful connection is logged."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock()
|
|
mock_models.data = []
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should log "OpenAI API key is valid"
|
|
pass
|
|
|
|
def test_openai_connection_logs_failure(self):
|
|
"""Test that failed connection is logged."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("API error")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should log error
|
|
pass
|
|
|
|
def test_openai_connection_logs_no_key(self):
|
|
"""Test that missing key is logged."""
|
|
from app.config import settings
|
|
|
|
with patch.object(settings, "openai_api_key", None):
|
|
# Should log warning
|
|
pass
|
|
|
|
def test_openai_connection_api_key_error_detection(self):
|
|
"""Test detection of API key related errors."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("api key is invalid")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# is_auth_error should be True (case insensitive check)
|
|
pass
|
|
|
|
def test_openai_connection_auth_error_detection(self):
|
|
"""Test detection of auth related errors."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("Authentication required")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# is_auth_error should be True (case insensitive check)
|
|
pass
|
|
|
|
def test_openai_connection_non_auth_error_detection(self):
|
|
"""Test that non-auth errors are not marked as auth errors."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_client.models.list.side_effect = Exception("Network timeout")
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# is_auth_error should be False
|
|
pass
|
|
|
|
def test_openai_connection_with_multiple_models(self):
|
|
"""Test connection returning multiple models."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock()
|
|
mock_models.data = [
|
|
{"id": "gpt-4"},
|
|
{"id": "gpt-3.5-turbo"},
|
|
{"id": "text-davinci-003"},
|
|
]
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# models_available should be 3
|
|
pass
|
|
|
|
def test_openai_connection_with_empty_models(self):
|
|
"""Test connection returning empty models list."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock()
|
|
mock_models.data = []
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-test-key"):
|
|
# Should still return success
|
|
# models_available should be 0
|
|
pass
|
|
|
|
def test_openai_connection_client_initialization(self):
|
|
"""Test that OpenAI client is initialized with correct API key."""
|
|
from app.config import settings
|
|
|
|
with patch("openai.OpenAI") as mock_openai_class:
|
|
mock_client = MagicMock()
|
|
mock_models = MagicMock()
|
|
mock_models.data = []
|
|
mock_client.models.list.return_value = mock_models
|
|
mock_openai_class.return_value = mock_client
|
|
|
|
with patch.object(settings, "openai_api_key", "sk-my-key"):
|
|
# OpenAI should be called with api_key="sk-my-key"
|
|
pass
|