@@ -122,15 +122,19 @@ def mock_api_client_fixture():
122122
123123@pytest .fixture
124124def mock_eval_dependencies (mock_api_client_fixture ):
125- with mock .patch ("google.cloud.storage.Client" ) as mock_storage_client , mock .patch (
126- "google.cloud.bigquery.Client"
127- ) as mock_bq_client , mock .patch (
128- "vertexai._genai.evals.Evals.evaluate_instances"
129- ) as mock_evaluate_instances , mock .patch (
130- "vertexai._genai._gcs_utils.GcsUtils.upload_json_to_prefix"
131- ) as mock_upload_to_gcs , mock .patch (
132- "vertexai._genai._evals_metric_loaders.LazyLoadedPrebuiltMetric._fetch_and_parse"
133- ) as mock_fetch_prebuilt_metric :
125+ with (
126+ mock .patch ("google.cloud.storage.Client" ) as mock_storage_client ,
127+ mock .patch ("google.cloud.bigquery.Client" ) as mock_bq_client ,
128+ mock .patch (
129+ "vertexai._genai.evals.Evals.evaluate_instances"
130+ ) as mock_evaluate_instances ,
131+ mock .patch (
132+ "vertexai._genai._gcs_utils.GcsUtils.upload_json_to_prefix"
133+ ) as mock_upload_to_gcs ,
134+ mock .patch (
135+ "vertexai._genai._evals_metric_loaders.LazyLoadedPrebuiltMetric._fetch_and_parse"
136+ ) as mock_fetch_prebuilt_metric ,
137+ ):
134138
135139 def mock_evaluate_instances_side_effect (* args , ** kwargs ):
136140 metric_config = kwargs .get ("metric_config" , {})
@@ -3386,14 +3390,8 @@ def test_run_inference_with_agent_engine_falls_back_to_managed_sessions_api(
33863390 assert inference_result .candidate_name == "agent_engine_0"
33873391
33883392 @mock .patch .object (_evals_utils , "EvalDatasetLoader" )
3389- @mock .patch ("vertexai._genai._evals_common.InMemorySessionService" ) # fmt: skip
3390- @mock .patch ("vertexai._genai._evals_common.Runner" )
3391- @mock .patch ("vertexai._genai._evals_common.LlmAgent" )
33923393 def test_run_inference_with_local_agent (
33933394 self ,
3394- mock_llm_agent ,
3395- mock_runner ,
3396- mock_session_service ,
33973395 mock_eval_dataset_loader ,
33983396 ):
33993397 mock_df = pd .DataFrame (
@@ -3421,8 +3419,15 @@ def test_run_inference_with_local_agent(
34213419 mock_agent_instance .instruction = "mock instruction"
34223420 mock_agent_instance .tools = []
34233421 mock_agent_instance .sub_agents = []
3424- mock_llm_agent .return_value = mock_agent_instance
3422+
3423+ # Mock ADK modules for lazy imports in _execute_local_agent_run_with_retry_async
3424+ mock_session_service = mock .MagicMock ()
34253425 mock_session_service .return_value .create_session = mock .AsyncMock ()
3426+ mock_runner = mock .MagicMock ()
3427+ mock_adk_sessions_module = mock .MagicMock ()
3428+ mock_adk_sessions_module .InMemorySessionService = mock_session_service
3429+ mock_adk_runners_module = mock .MagicMock ()
3430+ mock_adk_runners_module .Runner = mock_runner
34263431 mock_runner_instance = mock_runner .return_value
34273432 stream_run_return_value_1 = [
34283433 mock .Mock (
@@ -3473,10 +3478,19 @@ def run_async_side_effect(*args, **kwargs):
34733478
34743479 mock_runner_instance .run_async .side_effect = run_async_side_effect
34753480
3476- inference_result = self .client .evals .run_inference (
3477- agent = mock_agent_instance ,
3478- src = mock_df ,
3479- )
3481+ with mock .patch .dict (
3482+ sys .modules ,
3483+ {
3484+ "google.adk" : mock .MagicMock (),
3485+ "google.adk.sessions" : mock_adk_sessions_module ,
3486+ "google.adk.runners" : mock_adk_runners_module ,
3487+ "google.adk.agents" : mock .MagicMock (),
3488+ },
3489+ ):
3490+ inference_result = self .client .evals .run_inference (
3491+ agent = mock_agent_instance ,
3492+ src = mock_df ,
3493+ )
34803494
34813495 mock_eval_dataset_loader .return_value .load .assert_called_once_with (mock_df )
34823496 assert mock_session_service .call_count == 2
@@ -4178,21 +4192,23 @@ def test_run_agent_internal_multi_turn_with_agent(self, mock_run_agent):
41784192 ]
41794193 assert "mock_agent" in agent_data ["agents" ]
41804194
4181- @mock .patch ("vertexai._genai._evals_common.ADK_SessionInput" ) # fmt: skip
4182- @mock .patch ("vertexai._genai._evals_common.EvaluationGenerator" ) # fmt: skip
4183- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulator" ) # fmt: skip
4184- @mock .patch ("vertexai._genai._evals_common.ConversationScenario" ) # fmt: skip
4185- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulatorConfig" ) # fmt: skip
41864195 @pytest .mark .asyncio
4187- async def test_run_adk_user_simulation_with_intermediate_events (
4188- self ,
4189- mock_config ,
4190- mock_scenario ,
4191- mock_simulator ,
4192- mock_generator ,
4193- mock_session_input ,
4194- ):
4196+ async def test_run_adk_user_simulation_with_intermediate_events (self ):
41954197 """Tests that intermediate invocation events (e.g. tool calls) are parsed successfully."""
4198+ mock_scenario = mock .MagicMock ()
4199+ mock_config = mock .MagicMock ()
4200+ mock_simulator = mock .MagicMock ()
4201+ mock_generator = mock .MagicMock ()
4202+ mock_session_input = mock .MagicMock ()
4203+ mock_adk_eval_scenarios = mock .MagicMock ()
4204+ mock_adk_eval_scenarios .ConversationScenario = mock_scenario
4205+ mock_adk_eval_case = mock .MagicMock ()
4206+ mock_adk_eval_case .SessionInput = mock_session_input
4207+ mock_adk_eval_generator = mock .MagicMock ()
4208+ mock_adk_eval_generator .EvaluationGenerator = mock_generator
4209+ mock_adk_simulator_module = mock .MagicMock ()
4210+ mock_adk_simulator_module .LlmBackedUserSimulator = mock_simulator
4211+ mock_adk_simulator_module .LlmBackedUserSimulatorConfig = mock_config
41964212 row = pd .Series (
41974213 {
41984214 "starting_prompt" : "I want a laptop." ,
@@ -4245,7 +4261,19 @@ async def test_run_adk_user_simulation_with_intermediate_events(
42454261 mock_generator ._generate_inferences_from_root_agent = mock .AsyncMock (
42464262 return_value = [mock_invocation ]
42474263 )
4248- turns = await _evals_common ._run_adk_user_simulation (row , mock_agent )
4264+ with mock .patch .dict (
4265+ sys .modules ,
4266+ {
4267+ "google.adk" : mock .MagicMock (),
4268+ "google.adk.evaluation" : mock .MagicMock (),
4269+ "google.adk.evaluation.conversation_scenarios" : mock_adk_eval_scenarios ,
4270+ "google.adk.evaluation.eval_case" : mock_adk_eval_case ,
4271+ "google.adk.evaluation.evaluation_generator" : mock_adk_eval_generator ,
4272+ "google.adk.evaluation.simulation" : mock .MagicMock (),
4273+ "google.adk.evaluation.simulation.llm_backed_user_simulator" : mock_adk_simulator_module ,
4274+ },
4275+ ):
4276+ turns = await _evals_common ._run_adk_user_simulation (row , mock_agent )
42494277
42504278 assert len (turns ) == 1
42514279 turn = turns [0 ]
@@ -7086,20 +7114,50 @@ def test_build_request_payload_tool_use_quality_v1_with_agent_data_tool_call(
70867114class TestRunAdkUserSimulation :
70877115 """Unit tests for the _run_adk_user_simulation function."""
70887116
7089- @mock .patch ("vertexai._genai._evals_common.ADK_SessionInput" ) # fmt: skip
7090- @mock .patch ("vertexai._genai._evals_common.EvaluationGenerator" ) # fmt: skip
7091- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulator" ) # fmt: skip
7092- @mock .patch ("vertexai._genai._evals_common.ConversationScenario" ) # fmt: skip
7093- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulatorConfig" ) # fmt: skip
7117+ def _build_adk_mock_modules (self ):
7118+ """Builds mock ADK modules for lazy imports in _run_adk_user_simulation."""
7119+ mock_scenario_cls = mock .MagicMock ()
7120+ mock_config_cls = mock .MagicMock ()
7121+ mock_simulator_cls = mock .MagicMock ()
7122+ mock_generator_cls = mock .MagicMock ()
7123+ mock_session_input_cls = mock .MagicMock ()
7124+ mock_modules = {
7125+ "google.adk" : mock .MagicMock (),
7126+ "google.adk.evaluation" : mock .MagicMock (),
7127+ "google.adk.evaluation.conversation_scenarios" : mock .MagicMock (
7128+ ConversationScenario = mock_scenario_cls
7129+ ),
7130+ "google.adk.evaluation.eval_case" : mock .MagicMock (
7131+ SessionInput = mock_session_input_cls
7132+ ),
7133+ "google.adk.evaluation.evaluation_generator" : mock .MagicMock (
7134+ EvaluationGenerator = mock_generator_cls
7135+ ),
7136+ "google.adk.evaluation.simulation" : mock .MagicMock (),
7137+ "google.adk.evaluation.simulation.llm_backed_user_simulator" : mock .MagicMock (
7138+ LlmBackedUserSimulator = mock_simulator_cls ,
7139+ LlmBackedUserSimulatorConfig = mock_config_cls ,
7140+ ),
7141+ }
7142+ return (
7143+ mock_modules ,
7144+ mock_scenario_cls ,
7145+ mock_config_cls ,
7146+ mock_simulator_cls ,
7147+ mock_generator_cls ,
7148+ mock_session_input_cls ,
7149+ )
7150+
70947151 @pytest .mark .asyncio
7095- async def test_run_adk_user_simulation_success (
7096- self ,
7097- mock_config_cls ,
7098- mock_scenario_cls ,
7099- mock_simulator_cls ,
7100- mock_generator_cls ,
7101- mock_session_input_cls ,
7102- ):
7152+ async def test_run_adk_user_simulation_success (self ):
7153+ (
7154+ mock_modules ,
7155+ mock_scenario_cls ,
7156+ _ ,
7157+ _ ,
7158+ mock_generator_cls ,
7159+ mock_session_input_cls ,
7160+ ) = self ._build_adk_mock_modules ()
71037161 row = pd .Series (
71047162 {
71057163 "starting_prompt" : "start" ,
@@ -7119,7 +7177,8 @@ async def test_run_adk_user_simulation_success(
71197177 return_value = [mock_invocation ]
71207178 )
71217179
7122- turns = await _evals_common ._run_adk_user_simulation (row , mock_agent )
7180+ with mock .patch .dict (sys .modules , mock_modules ):
7181+ turns = await _evals_common ._run_adk_user_simulation (row , mock_agent )
71237182
71247183 assert len (turns ) == 1
71257184 turn = turns [0 ]
@@ -7138,40 +7197,26 @@ async def test_run_adk_user_simulation_success(
71387197 )
71397198 mock_session_input_cls .assert_called_once ()
71407199
7141- @mock .patch ("vertexai._genai._evals_common.ADK_SessionInput" ) # fmt: skip
7142- @mock .patch ("vertexai._genai._evals_common.EvaluationGenerator" ) # fmt: skip
7143- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulator" ) # fmt: skip
7144- @mock .patch ("vertexai._genai._evals_common.ConversationScenario" ) # fmt: skip
7145- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulatorConfig" ) # fmt: skip
71467200 @pytest .mark .asyncio
7147- async def test_run_adk_user_simulation_missing_columns (
7148- self ,
7149- mock_config_cls ,
7150- mock_scenario_cls ,
7151- mock_simulator_cls ,
7152- mock_generator_cls ,
7153- mock_session_input_cls ,
7154- ):
7201+ async def test_run_adk_user_simulation_missing_columns (self ):
7202+ mock_modules , _ , _ , _ , _ , _ = self ._build_adk_mock_modules ()
71557203 row = pd .Series ({"conversation_plan" : "plan" })
71567204 mock_agent = mock .Mock ()
71577205
7158- with pytest .raises (ValueError , match = "User simulation requires" ):
7159- await _evals_common ._run_adk_user_simulation (row , mock_agent )
7206+ with mock .patch .dict (sys .modules , mock_modules ):
7207+ with pytest .raises (ValueError , match = "User simulation requires" ):
7208+ await _evals_common ._run_adk_user_simulation (row , mock_agent )
71607209
7161- @mock .patch ("vertexai._genai._evals_common.ADK_SessionInput" ) # fmt: skip
7162- @mock .patch ("vertexai._genai._evals_common.EvaluationGenerator" ) # fmt: skip
7163- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulator" ) # fmt: skip
7164- @mock .patch ("vertexai._genai._evals_common.ConversationScenario" ) # fmt: skip
7165- @mock .patch ("vertexai._genai._evals_common.LlmBackedUserSimulatorConfig" ) # fmt: skip
71667210 @pytest .mark .asyncio
7167- async def test_run_adk_user_simulation_missing_session_inputs (
7168- self ,
7169- mock_config_cls ,
7170- mock_scenario_cls ,
7171- mock_simulator_cls ,
7172- mock_generator_cls ,
7173- mock_session_input_cls ,
7174- ):
7211+ async def test_run_adk_user_simulation_missing_session_inputs (self ):
7212+ (
7213+ mock_modules ,
7214+ mock_scenario_cls ,
7215+ _ ,
7216+ _ ,
7217+ mock_generator_cls ,
7218+ mock_session_input_cls ,
7219+ ) = self ._build_adk_mock_modules ()
71757220 row = pd .Series (
71767221 {
71777222 "starting_prompt" : "start" ,
@@ -7190,7 +7235,8 @@ async def test_run_adk_user_simulation_missing_session_inputs(
71907235 return_value = [mock_invocation ]
71917236 )
71927237
7193- await _evals_common ._run_adk_user_simulation (row , mock_agent )
7238+ with mock .patch .dict (sys .modules , mock_modules ):
7239+ await _evals_common ._run_adk_user_simulation (row , mock_agent )
71947240
71957241 mock_scenario_cls .assert_called_once_with (
71967242 starting_prompt = "start" ,
0 commit comments