@@ -2129,6 +2129,88 @@ def test_openapi_json_schema_accessible(test_app):
21292129 logger .info ("OpenAPI /openapi.json endpoint is accessible" )
21302130
21312131
2132+ @pytest .mark .skipif (
2133+ _compat .IS_A2A_V1 ,
2134+ reason = (
2135+ "0.3.x-only: mocks server.apps.A2AStarletteApplication (gone in 1.x)"
2136+ ),
2137+ )
2138+ def test_a2a_setup_reaches_application_build (
2139+ mock_session_service ,
2140+ mock_artifact_service ,
2141+ mock_memory_service ,
2142+ mock_agent_loader ,
2143+ mock_eval_sets_manager ,
2144+ mock_eval_set_results_manager ,
2145+ temp_agents_dir_with_a2a ,
2146+ monkeypatch ,
2147+ ):
2148+ """Regression test for the A2A setup silently failing.
2149+
2150+ A function-local ``import json`` made ``json`` a local for the whole
2151+ ``get_fast_api_app`` function, so the earlier ``json.load(agent.json)`` in
2152+ the A2A loop raised ``UnboundLocalError``. The surrounding ``except`` swallowed
2153+ it, so no A2A routes were ever mounted. This asserts the loop gets past the
2154+ ``json.load`` call and actually builds the A2A application.
2155+ """
2156+ with (
2157+ patch ("signal.signal" , return_value = None ),
2158+ patch (
2159+ "google.adk.cli.fast_api.create_session_service_from_options" ,
2160+ return_value = mock_session_service ,
2161+ ),
2162+ patch (
2163+ "google.adk.cli.fast_api.create_artifact_service_from_options" ,
2164+ return_value = mock_artifact_service ,
2165+ ),
2166+ patch (
2167+ "google.adk.cli.fast_api.create_memory_service_from_options" ,
2168+ return_value = mock_memory_service ,
2169+ ),
2170+ patch (
2171+ "google.adk.cli.fast_api.AgentLoader" ,
2172+ return_value = mock_agent_loader ,
2173+ ),
2174+ patch (
2175+ "google.adk.cli.fast_api.LocalEvalSetsManager" ,
2176+ return_value = mock_eval_sets_manager ,
2177+ ),
2178+ patch (
2179+ "google.adk.cli.fast_api.LocalEvalSetResultsManager" ,
2180+ return_value = mock_eval_set_results_manager ,
2181+ ),
2182+ patch (
2183+ "google.adk.cli.fast_api._create_task_store_from_options" ,
2184+ return_value = MagicMock (),
2185+ ),
2186+ patch ("google.adk.a2a.executor.a2a_agent_executor.A2aAgentExecutor" ),
2187+ patch ("a2a.server.request_handlers.DefaultRequestHandler" ),
2188+ patch ("a2a.types.AgentCard" , return_value = MagicMock ()),
2189+ patch ("a2a.server.apps.A2AStarletteApplication" ) as mock_a2a_app ,
2190+ ):
2191+ mock_app_instance = MagicMock ()
2192+ mock_app_instance .routes .return_value = []
2193+ mock_a2a_app .return_value = mock_app_instance
2194+
2195+ monkeypatch .chdir (temp_agents_dir_with_a2a )
2196+
2197+ get_fast_api_app (
2198+ agents_dir = "." ,
2199+ web = True ,
2200+ session_service_uri = "" ,
2201+ artifact_service_uri = "" ,
2202+ memory_service_uri = "" ,
2203+ allow_origins = ["*" ],
2204+ a2a = True ,
2205+ host = "127.0.0.1" ,
2206+ port = 8000 ,
2207+ )
2208+
2209+ # If json.load raised UnboundLocalError, execution never reaches the
2210+ # A2AStarletteApplication construction and this mock is never called.
2211+ assert mock_a2a_app .called
2212+
2213+
21322214@pytest .mark .skipif (
21332215 _compat .IS_A2A_V1 ,
21342216 reason = (
0 commit comments