mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
litellm_fix_mapped_tests_core: fix test isolation and mock injection issues
## Problem Four tests in litellm_mapped_tests_core were failing: 1. test_register_model_with_scientific_notation - KeyError due to test isolation issues 2. test_search_uses_registry_credentials - Mock not being called due to incorrect patch path 3. test_send_email_missing_api_key - Real API calls despite mocking 4. test_stream_transformation_error_sync - Mock not effective, real API called ## Solution ### test_register_model_with_scientific_notation - Use unique model name to avoid conflicts with other tests - Clear LRU caches before test to prevent stale data - Clean up model_cost entry after test ### test_search_uses_registry_credentials - Use patch.object() on the actual base_llm_http_handler instance - String-based patching for instance methods can fail; direct object patching is more reliable ### test_send_email_missing_api_key - Directly inject mock HTTP client into logger instance - This bypasses any caching issues that could cause the fixture mock to be ineffective ### test_stream_transformation_error_sync - Patch litellm.completion directly instead of the handler module's litellm reference - This ensures the mock is effective regardless of import order ## Regression These tests were affected by LRU caching added in #19606 and HTTP client caching.
This commit is contained in:
parent
ecb725f189
commit
9ddcdbcaf7
4 changed files with 37 additions and 14 deletions
|
|
@ -98,7 +98,7 @@ async def test_send_email_success(mock_env_vars, mock_httpx_client):
|
|||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_send_email_missing_api_key(mock_httpx_client):
|
||||
async def test_send_email_missing_api_key():
|
||||
# Block all HTTP requests at network level to prevent real API calls
|
||||
respx.post("https://api.resend.com/emails").mock(
|
||||
return_value=httpx.Response(200, json={"id": "test_email_id"})
|
||||
|
|
@ -117,13 +117,18 @@ async def test_send_email_missing_api_key(mock_httpx_client):
|
|||
subject = "Test Subject"
|
||||
html_body = "<p>Test email body</p>"
|
||||
|
||||
# Mock the response to avoid making real HTTP requests
|
||||
# Create mock HTTP client and inject it directly into the logger
|
||||
# This ensures the mock is used regardless of any caching issues
|
||||
mock_response = mock.Mock(spec=Response)
|
||||
mock_response.raise_for_status.return_value = None
|
||||
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {"id": "test_email_id"}
|
||||
mock_httpx_client.post.return_value = mock_response
|
||||
|
||||
mock_async_client = mock.AsyncMock()
|
||||
mock_async_client.post.return_value = mock_response
|
||||
|
||||
# Directly inject the mock client to bypass any caching
|
||||
logger.async_httpx_client = mock_async_client
|
||||
|
||||
# Send email
|
||||
await logger.send_email(
|
||||
|
|
@ -131,8 +136,8 @@ async def test_send_email_missing_api_key(mock_httpx_client):
|
|||
)
|
||||
|
||||
# Verify the HTTP client was called with None as the API key
|
||||
mock_httpx_client.post.assert_called_once()
|
||||
call_args = mock_httpx_client.post.call_args
|
||||
mock_async_client.post.assert_called_once()
|
||||
call_args = mock_async_client.post.call_args
|
||||
assert call_args[1]["headers"] == {"Authorization": "Bearer None"}
|
||||
finally:
|
||||
# Restore the original key if it existed
|
||||
|
|
|
|||
|
|
@ -183,10 +183,8 @@ def test_stream_transformation_error_sync():
|
|||
"translate_completion_output_params_streaming",
|
||||
return_value=None
|
||||
):
|
||||
# Mock litellm.completion at the module level where it's imported
|
||||
# We need to patch it in the handler module, not in litellm itself
|
||||
with patch("litellm.google_genai.adapters.handler.litellm") as mock_litellm:
|
||||
mock_litellm.completion.return_value = mock_stream
|
||||
# Patch litellm.completion directly to prevent real API calls
|
||||
with patch("litellm.completion", return_value=mock_stream):
|
||||
# Call the handler with stream=True and expect a ValueError
|
||||
with pytest.raises(ValueError, match="Failed to transform streaming response"):
|
||||
GenerateContentToCompletionHandler.generate_content_handler(
|
||||
|
|
|
|||
|
|
@ -2282,8 +2282,19 @@ def test_register_model_with_scientific_notation():
|
|||
"""
|
||||
Test that the register_model function can handle scientific notation in the model name.
|
||||
"""
|
||||
# Use a unique model name to avoid conflicts with other tests
|
||||
test_model_name = "test-scientific-notation-model-unique-12345"
|
||||
|
||||
# Clean up any pre-existing entry and clear caches
|
||||
if test_model_name in litellm.model_cost:
|
||||
del litellm.model_cost[test_model_name]
|
||||
|
||||
# Clear LRU caches that might have stale data
|
||||
from litellm.utils import get_model_info, _cached_get_model_info_helper, _invalidate_model_cost_lowercase_map
|
||||
_invalidate_model_cost_lowercase_map()
|
||||
|
||||
model_cost_dict = {
|
||||
"my-custom-model": {
|
||||
test_model_name: {
|
||||
"max_tokens": 8192,
|
||||
"input_cost_per_token": "3e-07",
|
||||
"output_cost_per_token": "6e-07",
|
||||
|
|
@ -2294,12 +2305,17 @@ def test_register_model_with_scientific_notation():
|
|||
|
||||
litellm.register_model(model_cost_dict)
|
||||
|
||||
registered_model = litellm.model_cost["my-custom-model"]
|
||||
registered_model = litellm.model_cost[test_model_name]
|
||||
print(registered_model)
|
||||
assert registered_model["input_cost_per_token"] == 3e-07
|
||||
assert registered_model["output_cost_per_token"] == 6e-07
|
||||
assert registered_model["litellm_provider"] == "openai"
|
||||
assert registered_model["mode"] == "chat"
|
||||
|
||||
# Clean up after test
|
||||
if test_model_name in litellm.model_cost:
|
||||
del litellm.model_cost[test_model_name]
|
||||
_invalidate_model_cost_lowercase_map()
|
||||
|
||||
|
||||
def test_reasoning_content_preserved_in_text_completion_wrapper():
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ def test_add_vector_store_to_registry():
|
|||
@respx.mock
|
||||
def test_search_uses_registry_credentials():
|
||||
"""search() should pull credentials from vector_store_registry when available"""
|
||||
# Import the actual instance to patch it correctly
|
||||
from litellm.vector_stores.main import base_llm_http_handler
|
||||
|
||||
# Block all HTTP requests at the network level to prevent real API calls
|
||||
respx.route().mock(return_value=httpx.Response(200, json={"object": "list", "data": []}))
|
||||
|
||||
|
|
@ -168,8 +171,9 @@ def test_search_uses_registry_credentials():
|
|||
) as mock_get_creds, patch(
|
||||
"litellm.vector_stores.main.ProviderConfigManager.get_provider_vector_stores_config",
|
||||
return_value=MagicMock(),
|
||||
), patch(
|
||||
"litellm.vector_stores.main.base_llm_http_handler.vector_store_search_handler",
|
||||
), patch.object(
|
||||
base_llm_http_handler,
|
||||
"vector_store_search_handler",
|
||||
return_value=mock_search_response,
|
||||
) as mock_handler:
|
||||
search(vector_store_id="vs1", query="test", litellm_logging_obj=logger)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue