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

150 lines
6.2 KiB
Python

from __future__ import annotations
from unittest.mock import AsyncMock, Mock
import aiohttp
import pytest
from yuxi.channels.adapters.twitch.helix import HelixClient
def _make_mock_resp(status: int, data: dict | None = None, body: str = "error"):
mock_resp = AsyncMock()
mock_resp.status = status
if data is not None:
mock_resp.json = AsyncMock(return_value=data)
mock_resp.text = AsyncMock(return_value=body)
mock_resp.__aenter__ = AsyncMock(return_value=mock_resp)
mock_resp.__aexit__ = AsyncMock(return_value=None)
return mock_resp
def _make_session(**methods):
session = AsyncMock()
session.closed = False
for name, return_value in methods.items():
setattr(session, name, Mock(return_value=return_value))
return session
class TestHelixGet:
@pytest.mark.asyncio
async def test_get_200_returns_data(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(
get=_make_mock_resp(200, {"data": [{"id": "123"}]})
)
result = await client._get("/helix/users", login="testuser")
assert result == {"data": [{"id": "123"}]}
@pytest.mark.asyncio
async def test_get_401_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(get=_make_mock_resp(401))
result = await client._get("/helix/users")
assert result is None
@pytest.mark.asyncio
async def test_get_404_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(get=_make_mock_resp(404))
result = await client._get("/helix/users")
assert result is None
@pytest.mark.asyncio
async def test_get_500_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(
get=_make_mock_resp(500, body="Internal Server Error")
)
result = await client._get("/helix/users")
assert result is None
@pytest.mark.asyncio
async def test_get_connection_error_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(get=AsyncMock(side_effect=aiohttp.ClientError("Connection refused")))
result = await client._get("/helix/users")
assert result is None
class TestHelixPost:
@pytest.mark.asyncio
async def test_create_eventsub_subscription_200(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(
post=_make_mock_resp(200, {"data": [{"id": "sub_123"}]})
)
result = await client.create_eventsub_subscription({"type": "channel.follow"})
assert result == "sub_123"
@pytest.mark.asyncio
async def test_create_eventsub_409_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(post=_make_mock_resp(409))
result = await client.create_eventsub_subscription({"type": "channel.follow"})
assert result is None
@pytest.mark.asyncio
async def test_create_eventsub_429_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(post=_make_mock_resp(429))
result = await client.create_eventsub_subscription({"type": "channel.follow"})
assert result is None
@pytest.mark.asyncio
async def test_create_eventsub_connection_error_returns_none(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(post=AsyncMock(side_effect=aiohttp.ClientError("Connection refused")))
result = await client.create_eventsub_subscription({"type": "channel.follow"})
assert result is None
@pytest.mark.asyncio
async def test_delete_eventsub_subscription_204(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(delete=_make_mock_resp(204))
result = await client.delete_eventsub_subscription("sub_123")
assert result is True
@pytest.mark.asyncio
async def test_delete_eventsub_connection_error(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(delete=AsyncMock(side_effect=aiohttp.ClientError("Connection refused")))
result = await client.delete_eventsub_subscription("sub_123")
assert result is False
class TestHelixToken:
@pytest.mark.asyncio
async def test_get_app_access_token_200(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(
post=_make_mock_resp(200, {"access_token": "app_token_123"})
)
result = await client.get_app_access_token("secret")
assert result is not None
@pytest.mark.asyncio
async def test_get_app_access_token_connection_error(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(post=AsyncMock(side_effect=aiohttp.ClientError("Connection refused")))
result = await client.get_app_access_token("secret")
assert result is None
@pytest.mark.asyncio
async def test_refresh_user_token_200(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(
post=_make_mock_resp(
200, {"access_token": "new_token", "refresh_token": "new_refresh"}
)
)
result = await client.refresh_user_token("secret", "refresh_123")
assert result is not None
@pytest.mark.asyncio
async def test_refresh_user_token_connection_error(self):
client = HelixClient(client_id="test_id", access_token="test_token")
client._session = _make_session(post=AsyncMock(side_effect=aiohttp.ClientError("Connection refused")))
result = await client.refresh_user_token("secret", "refresh_123")
assert result is None