Skip to content
Merged
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
14 changes: 11 additions & 3 deletions tests/unit/app/endpoints/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from fastapi import HTTPException, status
from fastapi import HTTPException, Request, status
from app.endpoints.config import config_endpoint_handler
from configuration import AppConfig

Expand All @@ -15,7 +15,11 @@ def test_config_endpoint_handler_configuration_not_loaded(mocker):
)
mocker.patch("app.endpoints.config.configuration", None)

request = None
request = Request(
scope={
"type": "http",
}
)
with pytest.raises(HTTPException) as e:
config_endpoint_handler(request)
assert e.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
Expand Down Expand Up @@ -49,7 +53,11 @@ def test_config_endpoint_handler_configuration_loaded():
}
cfg = AppConfig()
cfg.init_from_dict(config_dict)
request = None
request = Request(
scope={
"type": "http",
}
)
response = config_endpoint_handler(request)
assert response is not None
assert response == cfg.configuration
8 changes: 7 additions & 1 deletion tests/unit/app/endpoints/test_info.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Unit tests for the /info REST API endpoint."""

from fastapi import Request

from app.endpoints.info import info_endpoint_handler
from configuration import AppConfig

Expand Down Expand Up @@ -28,7 +30,11 @@ def test_info_endpoint():
}
cfg = AppConfig()
cfg.init_from_dict(config_dict)
request = None
request = Request(
scope={
"type": "http",
}
)
response = info_endpoint_handler(request)
assert response is not None
assert response.name is not None
Expand Down
9 changes: 8 additions & 1 deletion tests/unit/app/endpoints/test_metrics.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Unit tests for the /metrics REST API endpoint."""

from fastapi import Request

from app.endpoints.metrics import metrics_endpoint_handler


Expand All @@ -8,7 +10,12 @@ async def test_metrics_endpoint(mocker):
mock_setup_metrics = mocker.patch(
"app.endpoints.metrics.setup_model_metrics", return_value=None
)
response = await metrics_endpoint_handler(None)
request = Request(
scope={
"type": "http",
}
)
response = await metrics_endpoint_handler(request)
assert response is not None
assert response.status_code == 200
assert "text/plain" in response.headers["Content-Type"]
Expand Down
5 changes: 3 additions & 2 deletions tests/unit/app/endpoints/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ async def test_query_endpoint_handler_configuration_not_loaded(mocker):
)
mocker.patch("app.endpoints.query.configuration", None)

request = None
query = "What is OpenStack?"
query_request = QueryRequest(query=query)
with pytest.raises(HTTPException) as e:
await query_endpoint_handler(request, auth=["test-user", "", "token"])
await query_endpoint_handler(query_request, auth=["test-user", "", "token"])
assert e.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert e.value.detail["response"] == "Configuration is not loaded"

Expand Down
8 changes: 7 additions & 1 deletion tests/unit/app/endpoints/test_root.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
"""Unit tests for the / endpoint handler."""

from fastapi import Request

from app.endpoints.root import root_endpoint_handler


def test_root_endpoint():
"""Test the root endpoint handler."""
request = None
request = Request(
scope={
"type": "http",
}
)
response = root_endpoint_handler(request)
assert response is not None
44 changes: 37 additions & 7 deletions tests/unit/app/endpoints/test_streaming_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import pytest

from fastapi import HTTPException, status
from fastapi import HTTPException, Request, status
from fastapi.responses import StreamingResponse

from llama_stack_client import APIConnectionError
Expand Down Expand Up @@ -118,9 +118,14 @@ async def test_streaming_query_endpoint_handler_configuration_not_loaded(mocker)
query = "What is OpenStack?"
query_request = QueryRequest(query=query)

request = Request(
scope={
"type": "http",
}
)
# await the async function
with pytest.raises(HTTPException) as e:
await streaming_query_endpoint_handler(None, query_request, auth=MOCK_AUTH)
await streaming_query_endpoint_handler(request, query_request, auth=MOCK_AUTH)
assert e.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert e.detail["response"] == "Configuration is not loaded"

Comment on lines 127 to 131
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix pytest.raises assertions (must assert outside the context and use e.value)

Asserting on e.status_code/e.detail inside the with-block and without using e.value is incorrect and can raise AttributeError. Move assertions outside and use e.value.

with pytest.raises(HTTPException) as e:
    await streaming_query_endpoint_handler(request, query_request, auth=MOCK_AUTH)

assert e.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert e.value.detail["response"] == "Configuration is not loaded"
🤖 Prompt for AI Agents
In tests/unit/app/endpoints/test_streaming_query.py around lines 127 to 131, the
assertions on the HTTPException are incorrectly placed inside the pytest.raises
context and use e instead of e.value. Move the assertions outside the with-block
and change them to use e.value.status_code and e.value.detail to correctly
access the exception attributes.

Expand All @@ -145,9 +150,14 @@ async def test_streaming_query_endpoint_on_connection_error(mocker):
mock_async_lsc = mocker.patch("client.AsyncLlamaStackClientHolder.get_client")
mock_async_lsc.return_value = mock_client

request = Request(
scope={
"type": "http",
}
)
# await the async function
with pytest.raises(HTTPException) as e:
await streaming_query_endpoint_handler(None, query_request, auth=MOCK_AUTH)
await streaming_query_endpoint_handler(request, query_request, auth=MOCK_AUTH)
assert e.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert e.detail["response"] == "Configuration is not loaded"

Comment on lines 159 to 163
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Simulate connection error at the correct call and fix assertions and expected message

Two issues:

  • APIConnectionError should be raised by client.models.list(), not by accessing client.models.
  • Inside-with assertions and using e instead of e.value are incorrect.
  • The expected message for connection failures should be “Unable to connect to Llama Stack”.
# raise the error when listing models
mock_client.models.list.side_effect = APIConnectionError(request=query_request)

with pytest.raises(HTTPException) as e:
    await streaming_query_endpoint_handler(request, query_request, auth=MOCK_AUTH)

assert e.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert e.value.detail["response"] == "Unable to connect to Llama Stack"

Also, you can remove one of the duplicate patches:

# Keep just one
mocker.patch("client.AsyncLlamaStackClientHolder.get_client", return_value=mock_client)
🤖 Prompt for AI Agents
In tests/unit/app/endpoints/test_streaming_query.py around lines 159 to 163, fix
the test to simulate the APIConnectionError correctly by setting the side_effect
on mock_client.models.list() instead of accessing client.models. Move the
assertions outside the with block and use e.value for accessing the exception.
Update the expected error message to "Unable to connect to Llama Stack". Also,
remove the duplicate patch for AsyncLlamaStackClientHolder.get_client, keeping
only one instance.

Expand Down Expand Up @@ -256,9 +266,14 @@ async def _test_streaming_query_endpoint_handler(mocker, store_transcript=False)

query_request = QueryRequest(query=query)

request = Request(
scope={
"type": "http",
}
)
# Await the async function
response = await streaming_query_endpoint_handler(
None, query_request, auth=MOCK_AUTH
request, query_request, auth=MOCK_AUTH
)

# assert the response is a StreamingResponse
Expand Down Expand Up @@ -1259,8 +1274,13 @@ async def test_auth_tuple_unpacking_in_streaming_query_endpoint_handler(mocker):
"app.endpoints.streaming_query.is_transcripts_enabled", return_value=False
)

request = Request(
scope={
"type": "http",
}
)
await streaming_query_endpoint_handler(
None,
request,
QueryRequest(query="test query"),
auth=("user123", "username", "auth_token_123"),
mcp_headers=None,
Expand Down Expand Up @@ -1301,8 +1321,13 @@ async def test_streaming_query_endpoint_handler_no_tools_true(mocker):

query_request = QueryRequest(query="What is OpenStack?", no_tools=True)

request = Request(
scope={
"type": "http",
}
)
response = await streaming_query_endpoint_handler(
None, query_request, auth=MOCK_AUTH
request, query_request, auth=MOCK_AUTH
)

# Assert the response is a StreamingResponse
Expand Down Expand Up @@ -1341,8 +1366,13 @@ async def test_streaming_query_endpoint_handler_no_tools_false(mocker):

query_request = QueryRequest(query="What is OpenStack?", no_tools=False)

request = Request(
scope={
"type": "http",
}
)
response = await streaming_query_endpoint_handler(
None, query_request, auth=MOCK_AUTH
request, query_request, auth=MOCK_AUTH
)

# Assert the response is a StreamingResponse
Expand Down
Loading