Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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"})
Expand All @@ -117,22 +117,27 @@ 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(
from_email=from_email, to_email=to_email, subject=subject, html_body=html_body
)

# 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
Expand Down
6 changes: 2 additions & 4 deletions tests/test_litellm/google_genai/test_google_genai_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Comment on lines +186 to +187
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inconsistent with the async test approach at line 215 which patches litellm.google_genai.adapters.handler.litellm. Consider using the same direct patching approach for consistency

Suggested change
# Patch litellm.completion directly to prevent real API calls
with patch("litellm.completion", return_value=mock_stream):
with patch("litellm.google_genai.adapters.handler.litellm") as mock_litellm:
mock_litellm.completion = MagicMock(return_value=mock_stream)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/test_litellm/google_genai/test_google_genai_handler.py
Line: 186:187

Comment:
inconsistent with the async test approach at line 215 which patches `litellm.google_genai.adapters.handler.litellm`. Consider using the same direct patching approach for consistency

```suggestion
        with patch("litellm.google_genai.adapters.handler.litellm") as mock_litellm:
            mock_litellm.completion = MagicMock(return_value=mock_stream)
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

# Call the handler with stream=True and expect a ValueError
with pytest.raises(ValueError, match="Failed to transform streaming response"):
GenerateContentToCompletionHandler.generate_content_handler(
Expand Down
20 changes: 18 additions & 2 deletions tests/test_litellm/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_model_info and _cached_get_model_info_helper are imported but never used

Suggested change
from litellm.utils import get_model_info, _cached_get_model_info_helper, _invalidate_model_cost_lowercase_map
from litellm.utils import _invalidate_model_cost_lowercase_map
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/test_litellm/test_utils.py
Line: 2293:2293

Comment:
`get_model_info` and `_cached_get_model_info_helper` are imported but never used

```suggestion
    from litellm.utils import _invalidate_model_cost_lowercase_map
```

How can I resolve this? If you propose a fix, please make it concise.

_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",
Expand All @@ -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():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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": []}))

Expand Down Expand Up @@ -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)
Expand Down
Loading