1. 删除了 test/unit/external_systems/framework/ 下的废弃空测试目录 2. 修复多处测试断言逻辑、参数传递与测试数据构造 3. 新增日志级别、缓存令牌、流事件等DTO单元测试 4. 补充路由绑定、会话仓储、outbox仓储的测试覆盖 5. 更新测试用例中的异常类型、参数校验与业务逻辑断言
149 lines
4.3 KiB
Python
149 lines
4.3 KiB
Python
"""channels application 层单元测试共享 fixture。
|
||
|
||
提供 application 层被驱动仓储 / 能力端口桩(OutboxRepositoryPort /
|
||
MessageRepositoryPort / ChannelSessionRepositoryPort /
|
||
ChannelAccountRepositoryPort / PairingRepositoryPort /
|
||
AuditLogRepositoryPort / ConversationPort / TransactionPort / QueuePort /
|
||
ContentReviewRepositoryPort / UserIdentityRepositoryPort /
|
||
IdempotencyRepositoryPort / PersistencePort / RealtimeMetricsPort)。
|
||
|
||
桩使用 ``AsyncMock()``(异步端口)/ ``MagicMock()``(TransactionPort.begin
|
||
为同步方法),不实现真实逻辑;方法签名以
|
||
``yuxi.channels.contract.ports.driven`` 下的 Protocol 为准。单文件独有的
|
||
helper 应保留在对应测试文件内(见 testing-guidelines.md)。
|
||
|
||
注意:``TransactionPort.begin`` 在端口协议中为同步方法(返回
|
||
TransactionContext,由 ``async with`` 消费),因此 ``fake_transaction_port``
|
||
使用 ``MagicMock()`` 而非 ``AsyncMock()``,避免 ``begin`` 被误生成为协程。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from unittest.mock import AsyncMock, MagicMock
|
||
|
||
import pytest
|
||
from yuxi.channels.core.registry.plugin_registry import PluginRegistry
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_outbox_repo() -> AsyncMock:
|
||
"""OutboxRepositoryPort 桩。
|
||
|
||
预设 ``saveOutboxEntry`` / ``getOutboxEntry`` / ``updateOutboxEntry``
|
||
返回 None,``listPendingOutboxEntries`` 返回空列表。
|
||
"""
|
||
mock = AsyncMock()
|
||
mock.saveOutboxEntry.return_value = None
|
||
mock.getOutboxEntry.return_value = None
|
||
mock.updateOutboxEntry.return_value = None
|
||
mock.listPendingOutboxEntries.return_value = []
|
||
return mock
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_message_repo() -> AsyncMock:
|
||
"""MessageRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_session_repo() -> AsyncMock:
|
||
"""ChannelSessionRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_account_repo() -> AsyncMock:
|
||
"""ChannelAccountRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_pairing_repo() -> AsyncMock:
|
||
"""PairingRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_audit_log_repo() -> AsyncMock:
|
||
"""AuditLogRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_conversation_port() -> AsyncMock:
|
||
"""ConversationPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_transaction_port() -> MagicMock:
|
||
"""TransactionPort 桩。
|
||
|
||
``begin`` 为同步方法,返回一个 async context manager 桩
|
||
(``__aenter__`` / ``__aexit__`` / ``commit`` / ``rollback`` 均为
|
||
AsyncMock),供 ``async with transaction.begin() as tx:`` 使用。
|
||
"""
|
||
port = MagicMock()
|
||
tx_ctx = MagicMock()
|
||
tx_ctx.__aenter__ = AsyncMock(return_value=tx_ctx)
|
||
tx_ctx.__aexit__ = AsyncMock(return_value=None)
|
||
tx_ctx.commit = AsyncMock(return_value=None)
|
||
tx_ctx.rollback = AsyncMock(return_value=None)
|
||
port.begin.return_value = tx_ctx
|
||
return port
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_queue_port() -> AsyncMock:
|
||
"""QueuePort 桩,``enqueue`` 默认返回 "job-001"。"""
|
||
mock = AsyncMock()
|
||
mock.enqueue.return_value = "job-001"
|
||
return mock
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_content_review_repo() -> AsyncMock:
|
||
"""ContentReviewRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_user_identity_repo() -> AsyncMock:
|
||
"""UserIdentityRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_idempotency_repo() -> AsyncMock:
|
||
"""IdempotencyRepositoryPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_persistence_port() -> AsyncMock:
|
||
"""PersistencePort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_realtime_metrics() -> AsyncMock:
|
||
"""RealtimeMetricsPort 桩。"""
|
||
return AsyncMock()
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_plugin_registry() -> MagicMock:
|
||
"""PluginRegistry 桩。
|
||
|
||
预设 ``getPlugin`` / ``getPluginByChannelType`` / ``getPluginState``
|
||
返回 None,``listPlugins`` 返回空列表。供 application 层组件
|
||
(如 ChannelCircuitBreaker)注入使用。
|
||
"""
|
||
mock = MagicMock(spec=PluginRegistry)
|
||
mock.getPlugin.return_value = None
|
||
mock.getPluginByChannelType.return_value = None
|
||
mock.getPluginState.return_value = None
|
||
mock.listPlugins.return_value = []
|
||
return mock
|