ForcePilot/backend/test/unit/channel/startup/test_outbox_retry.py
Kris 6c95dc006a test: 新增渠道模块全链路单元测试用例与目录结构
完成渠道模块的单元测试目录搭建,新增多个领域模型、端口、中间件、事件、服务以及基础设施层的单元测试文件,同时补充了conftest.py的环境变量配置,完善测试基础环境。
2026-05-30 21:55:35 +08:00

117 lines
3.8 KiB
Python

from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from yuxi.channel.worker.outbox_retry import OutboxRetryWorker
class TestOutboxRetryWorker:
@pytest.fixture
def mock_outbox_repo(self):
return AsyncMock()
@pytest.fixture
def mock_adapters(self):
adapter = AsyncMock()
adapter.send_message.return_value = MagicMock(success=True)
return {"web": adapter}
@pytest.fixture
def worker(self, mock_outbox_repo, mock_adapters):
return OutboxRetryWorker(
outbox_repo=mock_outbox_repo,
adapters=mock_adapters,
poll_interval=1.0,
)
@pytest.mark.asyncio
async def test_start(self, worker):
await worker.start()
assert worker.is_running is True
@pytest.mark.asyncio
async def test_stop(self, worker):
await worker.start()
await worker.stop()
assert worker.is_running is False
@pytest.mark.asyncio
async def test_is_running_property(self, worker):
assert worker.is_running is False
await worker.start()
assert worker.is_running is True
@pytest.mark.asyncio
async def test_run_loop(self, worker, mock_outbox_repo):
entry = MagicMock()
entry.id = 1
entry.channel_type = "web"
entry.payload = {"content": "Hello"}
entry.retry_count = 0
mock_outbox_repo.dequeue_pending.return_value = [entry]
mock_outbox_repo.mark_delivered.return_value = True
await worker.start()
await worker.stop()
@pytest.mark.asyncio
async def test_retry_success(self, worker, mock_outbox_repo, mock_adapters):
entry = MagicMock()
entry.id = 1
entry.channel_type = "web"
entry.payload = {"content": "Hello"}
entry.retry_count = 0
mock_outbox_repo.dequeue_pending.return_value = [entry]
mock_outbox_repo.mark_delivered.return_value = True
await worker.start()
await worker.stop()
mock_adapters["web"].send_message.assert_awaited_once()
mock_outbox_repo.mark_delivered.assert_awaited_once_with(1)
@pytest.mark.asyncio
async def test_retry_failure(self, worker, mock_outbox_repo, mock_adapters):
entry = MagicMock()
entry.id = 1
entry.channel_type = "web"
entry.payload = {"content": "Hello"}
entry.retry_count = 0
mock_outbox_repo.dequeue_pending.return_value = [entry]
mock_adapters["web"].send_message.return_value = MagicMock(success=False)
mock_outbox_repo.mark_failed.return_value = True
await worker.start()
await worker.stop()
mock_outbox_repo.mark_failed.assert_awaited_once_with(1, "retry")
@pytest.mark.asyncio
async def test_retry_no_adapter(self, worker, mock_outbox_repo):
entry = MagicMock()
entry.id = 1
entry.channel_type = "unknown"
entry.payload = {"content": "Hello"}
entry.retry_count = 0
mock_outbox_repo.dequeue_pending.return_value = [entry]
mock_outbox_repo.mark_failed.return_value = True
await worker.start()
await worker.stop()
mock_outbox_repo.mark_failed.assert_awaited_once_with(1, "no adapter")
@pytest.mark.asyncio
async def test_retry_exception(self, worker, mock_outbox_repo, mock_adapters):
entry = MagicMock()
entry.id = 1
entry.channel_type = "web"
entry.payload = {"content": "Hello"}
entry.retry_count = 0
mock_outbox_repo.dequeue_pending.return_value = [entry]
mock_adapters["web"].send_message.side_effect = Exception("send error")
mock_outbox_repo.mark_failed.return_value = True
await worker.start()
await worker.stop()
mock_outbox_repo.mark_failed.assert_awaited_once_with(1, "send error")