"""Pytest 全局 fixture:把 actor 句柄、PostgresDatabase、loguru 等重副作用替换成可控 stub。""" from __future__ import annotations import types from typing import Any, Dict from unittest.mock import AsyncMock, MagicMock import pytest # ───────────────────────────────────────────────────────────────────────────── # actor 注册表存根:测试期把名字 -> mock 实例塞进进程内 actor 运行时。 # 生产代码 ``get_actor(name).method(args)`` 会拿到 LocalActorHandle 转发到 mock。 # mock 方法用 AsyncMock 即可(handle 统一返回 awaitable)。 # ───────────────────────────────────────────────────────────────────────────── class _FakeActorRegistry: """薄封装:``register(name, instance)`` 直接登记到真实 actor 运行时。""" def register(self, name: str, instance: Any) -> None: from kilostar.utils import actor actor.register_actor(name, instance) @pytest.fixture def fake_actors(monkeypatch) -> _FakeActorRegistry: """清空并接管进程内 actor 运行时,测试结束后复位。 用法:: def test_xxx(fake_actors): gsm = MagicMock() gsm.get_tool_config = AsyncMock(return_value={"api_key": "k"}) fake_actors.register("global_state_machine", gsm) """ from kilostar.utils import actor actor.clear_actors() yield _FakeActorRegistry() actor.clear_actors() @pytest.fixture def gsm_handle(fake_actors) -> MagicMock: """快捷 fixture:注册名为 ``global_state_machine`` 的 mock 实例并返回它。 方法默认为 ``AsyncMock``;生产侧 ``await get_actor(...).method(args)`` 正常工作。 """ gsm = MagicMock() fake_actors.register("global_state_machine", gsm) return gsm # ───────────────────────────────────────────────────────────────────────────── # 工具:构造一个 ``MCP_AVAILABLE`` 关闭的 mcp_helper 状态 # ───────────────────────────────────────────────────────────────────────────── @pytest.fixture def mcp_unavailable(monkeypatch): from kilostar.utils import mcp_helper monkeypatch.setattr(mcp_helper, "_MCP_AVAILABLE", False) yield