11"""Unit tests for tools endpoint."""
22
33import pytest
4+ from pytest_mock import MockerFixture , MockType
45from fastapi import HTTPException
56
67from llama_stack_client import APIConnectionError
78
9+ from authentication .interface import AuthTuple
10+
811# Import the function directly to bypass decorators
912from app .endpoints import tools
1013from models .responses import ToolsResponse
1720)
1821
1922# Shared mock auth tuple with 4 fields as expected by the application
20- MOCK_AUTH = ("mock_user_id" , "mock_username" , False , "mock_token" )
23+ MOCK_AUTH : AuthTuple = ("mock_user_id" , "mock_username" , False , "mock_token" )
2124
2225
2326@pytest .fixture
24- def mock_configuration ():
27+ def mock_configuration () -> Configuration :
2528 """Create a mock configuration with MCP servers."""
2629 return Configuration (
2730 name = "test" ,
@@ -44,7 +47,7 @@ def mock_configuration():
4447
4548
4649@pytest .fixture
47- def mock_tools_response (mocker ) :
50+ def mock_tools_response (mocker : MockerFixture ) -> list [ MockType ] :
4851 """Create mock tools response from LlamaStack client."""
4952 # Create mock tools that behave like dict when converted
5053 tool1 = mocker .Mock ()
@@ -102,8 +105,10 @@ def mock_tools_response(mocker):
102105
103106@pytest .mark .asyncio
104107async def test_tools_endpoint_success (
105- mocker , mock_configuration , mock_tools_response
106- ): # pylint: disable=redefined-outer-name
108+ mocker : MockerFixture ,
109+ mock_configuration : Configuration , # pylint: disable=redefined-outer-name
110+ mock_tools_response : list [MockType ], # pylint: disable=redefined-outer-name
111+ ) -> None :
107112 """Test successful tools endpoint response."""
108113 # Mock configuration
109114 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -161,7 +166,7 @@ async def test_tools_endpoint_success(
161166
162167
163168@pytest .mark .asyncio
164- async def test_tools_endpoint_no_mcp_servers (mocker ) :
169+ async def test_tools_endpoint_no_mcp_servers (mocker : MockerFixture ) -> None :
165170 """Test tools endpoint with no MCP servers configured."""
166171 # Mock configuration with no MCP servers
167172 mock_config = Configuration (
@@ -198,8 +203,9 @@ async def test_tools_endpoint_no_mcp_servers(mocker):
198203
199204@pytest .mark .asyncio
200205async def test_tools_endpoint_api_connection_error (
201- mocker , mock_configuration
202- ): # pylint: disable=redefined-outer-name
206+ mocker : MockerFixture , # pylint: disable=redefined-outer-name
207+ mock_configuration : Configuration , # pylint: disable=redefined-outer-name
208+ ) -> None :
203209 """Test tools endpoint with API connection error from individual servers."""
204210 # Mock configuration
205211 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -237,8 +243,10 @@ async def test_tools_endpoint_api_connection_error(
237243
238244@pytest .mark .asyncio
239245async def test_tools_endpoint_partial_failure ( # pylint: disable=redefined-outer-name
240- mocker , mock_configuration , mock_tools_response
241- ):
246+ mocker : MockerFixture ,
247+ mock_configuration : Configuration ,
248+ mock_tools_response : list [MockType ],
249+ ) -> None :
242250 """Test tools endpoint with one MCP server failing."""
243251 # Mock configuration
244252 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -283,8 +291,9 @@ async def test_tools_endpoint_partial_failure( # pylint: disable=redefined-oute
283291
284292@pytest .mark .asyncio
285293async def test_tools_endpoint_builtin_toolgroup (
286- mocker , mock_configuration
287- ): # pylint: disable=redefined-outer-name
294+ mocker : MockerFixture ,
295+ mock_configuration : Configuration , # pylint: disable=redefined-outer-name
296+ ) -> None :
288297 """Test tools endpoint with built-in toolgroups."""
289298 # Mock configuration
290299 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -336,7 +345,7 @@ async def test_tools_endpoint_builtin_toolgroup(
336345
337346
338347@pytest .mark .asyncio
339- async def test_tools_endpoint_mixed_toolgroups (mocker ) :
348+ async def test_tools_endpoint_mixed_toolgroups (mocker : MockerFixture ) -> None :
340349 """Test tools endpoint with both MCP and built-in toolgroups."""
341350 # Mock configuration with MCP servers
342351 mock_config = Configuration (
@@ -425,8 +434,9 @@ async def test_tools_endpoint_mixed_toolgroups(mocker):
425434
426435@pytest .mark .asyncio
427436async def test_tools_endpoint_value_attribute_error (
428- mocker , mock_configuration
429- ): # pylint: disable=redefined-outer-name
437+ mocker : MockerFixture ,
438+ mock_configuration : Configuration , # pylint: disable=redefined-outer-name
439+ ) -> None :
430440 """Test tools endpoint with ValueError/AttributeError in toolgroups.list."""
431441 # Mock configuration
432442 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -456,8 +466,8 @@ async def test_tools_endpoint_value_attribute_error(
456466
457467@pytest .mark .asyncio
458468async def test_tools_endpoint_apiconnection_error_toolgroups ( # pylint: disable=redefined-outer-name
459- mocker , mock_configuration
460- ):
469+ mocker : MockerFixture , mock_configuration : Configuration
470+ ) -> None :
461471 """Test tools endpoint with APIConnectionError in toolgroups.list."""
462472 # Mock configuration
463473 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -483,13 +493,16 @@ async def test_tools_endpoint_apiconnection_error_toolgroups( # pylint: disable
483493 await tools .tools_endpoint_handler .__wrapped__ (mock_request , mock_auth )
484494
485495 assert exc_info .value .status_code == 500
486- assert "Unable to connect to Llama Stack" in exc_info .value .detail ["response" ]
496+
497+ detail = exc_info .value .detail
498+ assert isinstance (detail , dict )
499+ assert "Unable to connect to Llama Stack" in detail ["response" ]
487500
488501
489502@pytest .mark .asyncio
490503async def test_tools_endpoint_client_holder_apiconnection_error ( # pylint: disable=redefined-outer-name
491- mocker , mock_configuration
492- ):
504+ mocker : MockerFixture , mock_configuration : Configuration
505+ ) -> None :
493506 """Test tools endpoint with APIConnectionError in client holder."""
494507 # Mock configuration
495508 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -511,13 +524,17 @@ async def test_tools_endpoint_client_holder_apiconnection_error( # pylint: disa
511524 await tools .tools_endpoint_handler .__wrapped__ (mock_request , mock_auth )
512525
513526 assert exc_info .value .status_code == 500
514- assert "Unable to connect to Llama Stack" in exc_info .value .detail ["response" ]
527+
528+ detail = exc_info .value .detail
529+ assert isinstance (detail , dict )
530+ assert "Unable to connect to Llama Stack" in detail ["response" ]
515531
516532
517533@pytest .mark .asyncio
518534async def test_tools_endpoint_general_exception (
519- mocker , mock_configuration
520- ): # pylint: disable=redefined-outer-name
535+ mocker : MockerFixture ,
536+ mock_configuration : Configuration , # pylint: disable=redefined-outer-name
537+ ) -> None :
521538 """Test tools endpoint with general exception."""
522539 # Mock configuration
523540 mocker .patch ("app.endpoints.tools.configuration" , mock_configuration )
@@ -540,4 +557,7 @@ async def test_tools_endpoint_general_exception(
540557 await tools .tools_endpoint_handler .__wrapped__ (mock_request , mock_auth )
541558
542559 assert exc_info .value .status_code == 500
543- assert "Unable to retrieve list of tools" in exc_info .value .detail ["response" ]
560+
561+ detail = exc_info .value .detail
562+ assert isinstance (detail , dict )
563+ assert "Unable to retrieve list of tools" in detail ["response" ]
0 commit comments