本次提交清理了多个单元测试文件中的多余空行,调整了部分导入的顺序,同时修复了一处feishu错误翻译的导入顺序问题,移除了application/conftest.py中未使用的fake_report_repo fixture,优化代码格式提升可读性。
132 lines
3.7 KiB
Python
132 lines
3.7 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
|
||
|
||
|
||
@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()
|