完成渠道模块的单元测试目录搭建,新增多个领域模型、端口、中间件、事件、服务以及基础设施层的单元测试文件,同时补充了conftest.py的环境变量配置,完善测试基础环境。
114 lines
4.8 KiB
Python
114 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
|
|
from yuxi.channel.application.service.inbound_service import InboundService
|
|
from yuxi.channel.domain.model.message.unified_message import UnifiedMessage
|
|
from yuxi.channel.domain.model.message.peer import Peer
|
|
from yuxi.channel.domain.service.message_context import MessageContext
|
|
from yuxi.channel.domain.service.pipeline import Pipeline
|
|
|
|
|
|
class TestInboundService:
|
|
@pytest.fixture
|
|
def mock_pipeline(self):
|
|
pipeline = MagicMock(spec=Pipeline)
|
|
pipeline.execute = AsyncMock(return_value=MagicMock(spec=MessageContext))
|
|
return pipeline
|
|
|
|
@pytest.fixture
|
|
def mock_event_publisher(self):
|
|
return AsyncMock()
|
|
|
|
@pytest.fixture
|
|
def mock_message_log_repo(self):
|
|
return AsyncMock()
|
|
|
|
@pytest.fixture
|
|
def sample_message(self):
|
|
return UnifiedMessage(
|
|
message_id="msg123",
|
|
channel_type="web",
|
|
sender=Peer(id="user1", name="User"),
|
|
content="Hello",
|
|
)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_basic(self, mock_pipeline, sample_message):
|
|
service = InboundService(mock_pipeline)
|
|
result = await service.submit(sample_message, channel_type="web")
|
|
mock_pipeline.execute.assert_awaited_once()
|
|
assert result is not None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_with_trace_id(self, mock_pipeline, sample_message):
|
|
service = InboundService(mock_pipeline)
|
|
result = await service.submit(sample_message, channel_type="web", trace_id="trace123")
|
|
ctx = mock_pipeline.execute.call_args[0][0]
|
|
assert ctx.trace_id == "trace123"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_creates_log(self, mock_pipeline, sample_message, mock_message_log_repo):
|
|
service = InboundService(mock_pipeline, message_log_repo=mock_message_log_repo)
|
|
await service.submit(sample_message, channel_type="web")
|
|
mock_message_log_repo.create_log.assert_awaited_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_publishes_event(self, mock_pipeline, sample_message, mock_event_publisher):
|
|
service = InboundService(mock_pipeline, event_publisher=mock_event_publisher)
|
|
await service.submit(sample_message, channel_type="web")
|
|
mock_event_publisher.publish.assert_not_awaited()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_aborted_message(self, mock_pipeline, sample_message, mock_event_publisher):
|
|
aborted_ctx = MagicMock(spec=MessageContext)
|
|
aborted_ctx.is_aborted = True
|
|
aborted_ctx.is_skipped = False
|
|
aborted_ctx.message = sample_message
|
|
aborted_ctx.trace_id = "trace123"
|
|
aborted_ctx.abort_reason = "test abort"
|
|
aborted_ctx.abort_code = "TEST_ABORT"
|
|
mock_pipeline.execute = AsyncMock(return_value=aborted_ctx)
|
|
|
|
service = InboundService(mock_pipeline, event_publisher=mock_event_publisher)
|
|
await service.submit(sample_message, channel_type="web")
|
|
mock_event_publisher.publish.assert_awaited_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_skipped_message(self, mock_pipeline, sample_message, mock_event_publisher):
|
|
skipped_ctx = MagicMock(spec=MessageContext)
|
|
skipped_ctx.is_aborted = False
|
|
skipped_ctx.is_skipped = True
|
|
skipped_ctx.message = sample_message
|
|
skipped_ctx.trace_id = "trace123"
|
|
mock_pipeline.execute = AsyncMock(return_value=skipped_ctx)
|
|
|
|
service = InboundService(mock_pipeline, event_publisher=mock_event_publisher)
|
|
await service.submit(sample_message, channel_type="web")
|
|
mock_event_publisher.publish.assert_not_awaited()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_log_exception_handling(self, mock_pipeline, sample_message, mock_message_log_repo):
|
|
mock_message_log_repo.create_log.side_effect = Exception("log error")
|
|
service = InboundService(mock_pipeline, message_log_repo=mock_message_log_repo)
|
|
result = await service.submit(sample_message, channel_type="web")
|
|
assert result is not None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_event_exception_handling(self, mock_pipeline, sample_message, mock_event_publisher):
|
|
mock_event_publisher.publish.side_effect = Exception("publish error")
|
|
aborted_ctx = MagicMock(spec=MessageContext)
|
|
aborted_ctx.is_aborted = True
|
|
aborted_ctx.is_skipped = False
|
|
aborted_ctx.message = sample_message
|
|
aborted_ctx.trace_id = "trace123"
|
|
aborted_ctx.abort_reason = "test"
|
|
aborted_ctx.abort_code = "TEST"
|
|
mock_pipeline.execute = AsyncMock(return_value=aborted_ctx)
|
|
|
|
service = InboundService(mock_pipeline, event_publisher=mock_event_publisher)
|
|
result = await service.submit(sample_message, channel_type="web")
|
|
assert result is not None
|