ForcePilot/backend/test/unit/channels/conftest.py
Kris 08617091dc refactor: 整理项目包结构与导入路径
- 新增多个业务域的__init__.py模块文件,规范包导出结构
- 调整多个DTO文件的导入路径,统一模块组织方式
- 移除测试文件中多余的空行与导入语句
- 优化部分业务模块的包层级划分
2026-07-18 02:04:03 +08:00

153 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""channels 限界上下文单元测试跨层通用 fixture。
本文件提供横跨 core / application / adapters / plugins 各层复用的被驱动
端口桩LoggerPort / ConfigPort / CachePort / EventPublisherPort /
TracerPort。桩使用 ``unittest.mock`` 的 ``MagicMock`` / ``AsyncMock``
不实现真实逻辑;端口方法签名以 ``yuxi.channels.contract.ports.driven``
下的 Protocol 为准。
注意LoggerPort / TracerPort 的方法在端口协议中均为 ``async def``,因此
此处使用 ``MagicMock(spec=...)`` —— MagicMock 会自动为 async 方法生成
AsyncMock可 ``await``),与端口协议保持一致。单文件独有的 helper 应保
留在对应测试文件内(见 testing-guidelines.md
"""
from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from yuxi.channels.contract.ports.driven.config.config_port import ConfigPort
from yuxi.channels.contract.ports.driven.messaging.event_publisher_port import (
EventPublisherPort,
)
from yuxi.channels.contract.ports.driven.shared.cache_port import CachePort
from yuxi.channels.contract.ports.driven.shared.logger_port import LoggerPort
from yuxi.channels.contract.ports.driven.shared.tracer_port import TracerPort
from yuxi.channels.core.config.config_manager import ConfigManager
@pytest.fixture
def fake_logger() -> LoggerPort:
"""LoggerPort 桩。
``MagicMock(spec=LoggerPort)`` 自动为 ``log`` / ``debug`` / ``info`` /
``warning`` / ``error`` / ``exception`` 生成 AsyncMock可 ``await``
默认返回 None。需要断言调用参数时直接使用对应方法的 ``assert_*``。
"""
return MagicMock(spec=LoggerPort)
@pytest.fixture
def fake_config() -> ConfigPort:
"""ConfigPort 桩,``get`` 默认返回 None``update`` 默认返回 None。"""
mock = AsyncMock(spec=ConfigPort)
mock.get.return_value = None
mock.update.return_value = None
return mock
@pytest.fixture
def fake_config_manager() -> ConfigManager:
"""ConfigManager 桩。
``AsyncMock(spec=ConfigManager)`` 自动为 ``update`` / ``updateInternal``
/ ``rollback`` 等 async 方法生成 AsyncMock。``update`` /
``updateInternal`` 默认返回 None调用方按需覆盖返回值。
"""
mock = AsyncMock(spec=ConfigManager)
mock.update.return_value = None
mock.updateInternal.return_value = None
return mock
@pytest.fixture
def fake_cache() -> CachePort:
"""CachePort 桩,预设常用方法返回值。
``get`` 返回 None``set`` / ``delete`` / ``expire`` /
``acquireAdvisoryLock`` / ``releaseAdvisoryLock`` / ``ping`` 返回 True
``incr`` 返回 1。
"""
mock = AsyncMock(spec=CachePort)
mock.get.return_value = None
mock.set.return_value = True
mock.delete.return_value = True
mock.incr.return_value = 1
mock.expire.return_value = True
mock.acquireAdvisoryLock.return_value = True
mock.releaseAdvisoryLock.return_value = True
mock.ping.return_value = True
return mock
@pytest.fixture
def fake_event_publisher() -> EventPublisherPort:
"""EventPublisherPort 桩,``publish`` 默认返回 None。"""
mock = AsyncMock(spec=EventPublisherPort)
mock.publish.return_value = None
return mock
@pytest.fixture
def fake_tracer() -> TracerPort:
"""TracerPort 桩。
``MagicMock(spec=TracerPort)`` 自动为 ``startSpan`` / ``endSpan`` /
``getCurrentTrace`` 生成 AsyncMock可 ``await``)。``startSpan`` 默认
返回 Span-like MagicMock``endSpan`` 返回 None``getCurrentTrace``
返回 Option-like MagicMock调用方可按需覆盖。
"""
mock = MagicMock(spec=TracerPort)
mock.startSpan.return_value = MagicMock()
mock.endSpan.return_value = None
mock.getCurrentTrace.return_value = MagicMock()
return mock
@pytest.fixture
def fake_plugin_host() -> MagicMock:
"""PluginHost 桩(跨层共享)。
``MagicMock()`` 模拟 ``PluginHost`` 协议
``yuxi.channels.contract.plugin.entry.PluginHost``
- 所有 ``getXxxPort()`` 返回 ``MagicMock`` 桩(调用方可覆盖为带
``spec`` 的端口桩,如 ``host.getLoggerPort.return_value = fake_logger``
- ``registerAdapter()`` / ``registerStageSlot()`` / ``registerEventSubscription()``
/ ``registerConfigSource()`` / ``registerMatchTier()`` / ``registerMatcher()``
返回 ``None``
- ``publishEvent`` 为 ``AsyncMock``(可 ``await``),返回 ``None``。
本 fixture 提升至 channels 限界上下文根 conftest供 application/lifecycle
与 plugins 各层测试复用(避免在子目录 conftest 重复定义)。
"""
host = MagicMock()
# 端口获取:返回 MagicMock 桩,调用方可覆盖为带 spec 的端口桩
host.getConfigPort.return_value = MagicMock()
host.getLoggerPort.return_value = MagicMock()
host.getPersistencePort.return_value = MagicMock()
host.getCachePort.return_value = MagicMock()
host.getTracerPort.return_value = MagicMock()
host.getQueuePort.return_value = MagicMock()
host.getConversationPort.return_value = MagicMock()
host.getAgentRunPort.return_value = MagicMock()
host.getIdentityResolverPort.return_value = MagicMock()
host.getChannelAccountRepositoryPort.return_value = MagicMock()
host.getChannelSessionRepositoryPort.return_value = MagicMock()
host.getPairingRepositoryPort.return_value = MagicMock()
host.getAuditLogRepositoryPort.return_value = MagicMock()
host.getOutboxRepositoryPort.return_value = MagicMock()
host.getUserIdentityRepositoryPort.return_value = MagicMock()
host.getIdempotencyRepositoryPort.return_value = MagicMock()
host.getPersistenceHealthPort.return_value = MagicMock()
# 扩展点注册:返回 None
host.registerAdapter.return_value = None
host.registerStageSlot.return_value = None
host.registerEventSubscription.return_value = None
host.registerConfigSource.return_value = None
host.registerMatchTier.return_value = None
host.registerMatcher.return_value = None
# 事件发布async def使用 AsyncMock
host.publishEvent = AsyncMock(return_value=None)
return host