ForcePilot/backend/test/unit/channel/message/test_dedupe.py
Kris bab30f2715
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Ruff Format Check / Ruff Format & Lint (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
feat:0715
2026-07-15 12:30:58 +08:00

97 lines
3.4 KiB
Python

from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from yuxi.channel.constants import CHANNEL_PROCESSED_TTL_SECONDS, channel_processed_key
from yuxi.channel.message.dedupe import MessageDeduper
@pytest.fixture
def redis_mock():
return MagicMock(
set=AsyncMock(),
exists=AsyncMock(),
setex=AsyncMock(),
)
@pytest.fixture
def deduper():
return MessageDeduper()
async def test_is_processed_new_message(redis_mock, deduper):
redis_mock.set.return_value = True
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
result = await deduper.is_processed("msg-1")
assert result is False
redis_mock.set.assert_awaited_once_with(
channel_processed_key("msg-1"), "1", nx=True, ex=CHANNEL_PROCESSED_TTL_SECONDS
)
async def test_is_processed_duplicate_message(redis_mock, deduper):
redis_mock.set.return_value = None
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
result = await deduper.is_processed("msg-1")
assert result is True
async def test_is_processed_empty_message_id_returns_true(redis_mock, deduper):
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
assert await deduper.is_processed("") is True
assert await deduper.is_processed(None) is True
redis_mock.set.assert_not_called()
async def test_is_already_processed_true(redis_mock, deduper):
redis_mock.exists.return_value = 1
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
result = await deduper.is_already_processed("msg-1")
assert result is True
redis_mock.exists.assert_awaited_once_with(channel_processed_key("msg-1"))
async def test_is_already_processed_false(redis_mock, deduper):
redis_mock.exists.return_value = 0
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
result = await deduper.is_already_processed("msg-1")
assert result is False
async def test_is_already_processed_empty_message_id_returns_true(redis_mock, deduper):
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
assert await deduper.is_already_processed("") is True
redis_mock.exists.assert_not_called()
async def test_mark_processed_sets_key_with_ttl(redis_mock, deduper):
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
await deduper.mark_processed("msg-1")
redis_mock.setex.assert_awaited_once_with(channel_processed_key("msg-1"), CHANNEL_PROCESSED_TTL_SECONDS, "1")
async def test_mark_processed_empty_message_id_is_noop(redis_mock, deduper):
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
await deduper.mark_processed("")
await deduper.mark_processed(None)
redis_mock.setex.assert_not_called()
async def test_custom_ttl(redis_mock):
deduper = MessageDeduper(ttl_seconds=60)
redis_mock.set.return_value = True
with patch("yuxi.channel.message.dedupe.get_redis_client", AsyncMock(return_value=redis_mock)):
await deduper.is_processed("msg-1")
redis_mock.set.assert_awaited_once_with(channel_processed_key("msg-1"), "1", nx=True, ex=60)