def test_cli_eval_success_path(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
  """Test the success path of `adk eval` by fully executing it with a stub module, up to summary generation."""
  import asyncio
  import sys
  import types

  # stub cli_eval module
  stub = types.ModuleType("google.adk.cli.cli_eval")
  eval_sets_manager_stub = types.ModuleType(
      "google.adk.evaluation.local_eval_sets_manager"
  )

  class _EvalMetric:

    def __init__(self, metric_name: str, threshold: float) -> None:
      ...

  class _EvalCaseResult(BaseModel):
    eval_set_id: str
    eval_id: str
    final_eval_status: Any
    user_id: str
    session_id: str
    session_details: Optional[Session] = None
    eval_metric_results: list = {}
    overall_eval_metric_results: list = {}
    eval_metric_result_per_invocation: list = {}

  class EvalCase(BaseModel):
    eval_id: str

  class EvalSet(BaseModel):
    eval_set_id: str
    eval_cases: list[EvalCase]

  def mock_save_eval_set_result(cls, *args, **kwargs):
    return None

  monkeypatch.setattr(
      local_eval_set_results_manager.LocalEvalSetResultsManager,
      "save_eval_set_result",
      mock_save_eval_set_result,
  )

  # minimal enum-like namespace
  _EvalStatus = types.SimpleNamespace(PASSED="PASSED", FAILED="FAILED")

  # helper funcs
  stub.EvalMetric = _EvalMetric
  stub.EvalCaseResult = _EvalCaseResult
  stub.EvalStatus = _EvalStatus
  stub.MISSING_EVAL_DEPENDENCIES_MESSAGE = "stub msg"

  stub.get_evaluation_criteria_or_default = lambda _p: {"foo": 1.0}
  stub.get_root_agent = lambda _p: object()
  stub.try_get_reset_func = lambda _p: None
  stub.parse_and_get_evals_to_run = lambda _paths: {"set1.json": ["e1", "e2"]}
  eval_sets_manager_stub.load_eval_set_from_file = lambda x, y: EvalSet(
      eval_set_id="test_eval_set_id",
      eval_cases=[EvalCase(eval_id="e1"), EvalCase(eval_id="e2")],
  )

  # Create an async generator function for run_evals
  async def mock_run_evals(*_a, **_k):
    yield _EvalCaseResult(
        eval_set_id="set1.json",
        eval_id="e1",
        final_eval_status=_EvalStatus.PASSED,
        user_id="user",
        session_id="session1",
        overall_eval_metric_results=[{
            "metricName": "some_metric",
            "threshold": 0.0,
            "score": 1.0,
            "evalStatus": _EvalStatus.PASSED,
        }],
    )
    yield _EvalCaseResult(
        eval_set_id="set1.json",
        eval_id="e2",
        final_eval_status=_EvalStatus.FAILED,
        user_id="user",
        session_id="session2",
        overall_eval_metric_results=[{
            "metricName": "some_metric",
            "threshold": 0.0,
            "score": 0.0,
            "evalStatus": _EvalStatus.FAILED,
        }],
    )

  stub.run_evals = mock_run_evals

  # Replace asyncio.run with a function that properly handles coroutines
  def mock_asyncio_run(coro):
    # Create a new event loop
    loop = asyncio.new_event_loop()
    try:
      return loop.run_until_complete(coro)
    finally:
      loop.close()

  monkeypatch.setattr(cli_tools_click.asyncio, "run", mock_asyncio_run)

  # inject stub
  monkeypatch.setitem(sys.modules, "google.adk.cli.cli_eval", stub)
  monkeypatch.setitem(
      sys.modules,
      "google.adk.evaluation.local_eval_sets_manager",
      eval_sets_manager_stub,
  )

  # create dummy agent directory
  agent_dir = tmp_path / "agent5"
  agent_dir.mkdir()
  (agent_dir / "__init__.py").touch()

  # inject monkeypatch
  monkeypatch.setattr(
      cli_tools_click.envs, "load_dotenv_for_agent", lambda *a, **k: None
  )

  runner = CliRunner()
  result = runner.invoke(
      cli_tools_click.main,
      ["eval", str(agent_dir), str(tmp_path / "dummy_eval.json")],
  )

  assert result.exit_code == 0
  assert "Eval Run Summary" in result.output
  assert "Tests passed: 1" in result.output
  assert "Tests failed: 1" in result.output
Test the success path of `adk eval` by fully executing it with a stub module, up to summary generation.
tests/unittests/cli/utils/test_cli_tools_click.py