ForcePilot/backend/test/unit/channels/test_config_watcher.py
Kris 3264900bc9 test: 新增多渠道单元测试用例并配置测试环境变量
新增了Twitch、Telegram、Discord、Slack、Mattermost、WeChat、Zalo等多渠道的单元测试用例,覆盖了令牌处理、速率限制、消息去重、会话解析、格式转换、安全策略等模块
同时在测试配置中添加了测试用的OpenAI API密钥环境变量
2026-05-12 00:56:47 +08:00

120 lines
3.8 KiB
Python

from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from yuxi.channels.infra.config_watcher import ConfigWatcher
class TestConfigWatcherInit:
def test_default_values(self):
manager = MagicMock()
watcher = ConfigWatcher(manager)
assert watcher._last_config_hash is None
assert watcher._watched_prefixes == ["channels"]
assert watcher._noop_prefixes == []
assert watcher._running is False
def test_set_watched_prefixes(self):
manager = MagicMock()
watcher = ConfigWatcher(manager)
watcher.set_watched_prefixes(["channels.wechat", "channels.telegram"])
assert watcher._watched_prefixes == ["channels.wechat", "channels.telegram"]
def test_set_noop_prefixes(self):
manager = MagicMock()
watcher = ConfigWatcher(manager)
watcher.set_noop_prefixes(["channels.wechat.logLevel"])
assert watcher._noop_prefixes == ["channels.wechat.logLevel"]
class TestConfigWatcherCompute:
def test_compute_config_hash_consistent(self):
manager = MagicMock()
manager._channels_config = {"wx": {"enabled": True}}
watcher = ConfigWatcher(manager)
h1 = watcher._compute_config_hash()
h2 = watcher._compute_config_hash()
assert h1 == h2
def test_compute_config_hash_changes_with_config(self):
manager = MagicMock()
manager._channels_config = {"wx": {"enabled": True}}
watcher = ConfigWatcher(manager)
h1 = watcher._compute_config_hash()
manager._channels_config = {"wx": {"enabled": False}}
h2 = watcher._compute_config_hash()
assert h1 != h2
class TestConfigWatcherDiff:
def test_compute_diff_new_channel(self):
manager = MagicMock()
manager._channels_config = {"wx": {"enabled": True}}
manager._adapters = {}
watcher = ConfigWatcher(manager)
diff = watcher._compute_config_diff()
assert diff == {"wx": {"action": "start", "config": {"enabled": True}}}
def test_compute_diff_stopped_channel(self):
manager = MagicMock()
manager._channels_config = {}
manager._adapters = {"wx": MagicMock()}
watcher = ConfigWatcher(manager)
diff = watcher._compute_config_diff()
assert diff == {"wx": {"action": "stop"}}
def test_compute_diff_changed_channel(self):
manager = MagicMock()
manager._channels_config = {"wx": {"enabled": True}}
manager._adapters = {"wx": MagicMock()}
watcher = ConfigWatcher(manager)
diff = watcher._compute_config_diff()
assert diff == {"wx": {"action": "restart"}}
class TestConfigWatcherLifecycle:
@pytest.mark.asyncio
async def test_watch_starts_and_stops(self):
manager = MagicMock()
manager._channels_config = {}
manager._adapters = {}
watcher = ConfigWatcher(manager)
await watcher.watch(interval=60.0)
assert watcher._running is True
assert watcher._task is not None
await watcher.stop()
assert watcher._running is False
@pytest.mark.asyncio
async def test_watch_idempotent(self):
manager = MagicMock()
manager._channels_config = {}
manager._adapters = {}
watcher = ConfigWatcher(manager)
await watcher.watch(interval=60.0)
task1 = watcher._task
await watcher.watch(interval=60.0)
assert watcher._task is task1
await watcher.stop()
@pytest.mark.asyncio
async def test_reload_now_no_keys(self):
manager = MagicMock()
manager._channels_config = {"wx": {"enabled": True}}
manager._adapters = {}
manager.start_channel = AsyncMock()
watcher = ConfigWatcher(manager)
result = await watcher.reload_now()
assert "wx" in result