"""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()