本次提交修复了多个测试文件中的问题: 1. 为各管道测试类添加tracer_port属性初始化 2. 修复QQBot客户端关闭异常的错误类型匹配 3. 修正配对接口查询的状态值小写格式 4. 移除ChannelType枚举值的显式.value调用 5. 新增QQ常量的导出项与Instagram测试桩函数 6. 修复API接口返回值解析,正确访问data字段 7. 调整企业微信富文本消息的断言结构 8. 修正微信iLink的消息类型测试用例 9. 替换废弃的datetime.utc相关导入为UTC常量 10. 修复QQBot白名单适配器的返回值结构 11. 调整outbox工具的channel_msg_id处理逻辑 12. 新增多个适配器与服务的测试用例,覆盖异常降级、缓存处理等场景 13. 重构部分QQBot适配器的辅助函数测试,清理冗余代码 14. 修复微信iLink客户端的上传接口调用参数与缓存清理逻辑 15. 修正配置导出接口的敏感字段过滤与返回值结构
124 lines
4.4 KiB
Python
124 lines
4.4 KiB
Python
"""channels plugins/wecom 层单元测试共享 fixture。
|
||
|
||
提供 ``fake_wecom_client`` 桩,模拟 ``WecomClient``
|
||
(``yuxi.channels.plugins.wecom.wecom_client.WecomClient``)。wecom 适配器
|
||
测试通过此桩注入客户端依赖,不发起真实 HTTP 请求。
|
||
|
||
另提供 ``_make_cache`` / ``_make_logger`` / ``_make_config`` 辅助工厂,
|
||
构造 ``CachePort`` / ``LoggerPort`` / ``ConfigPort`` 的 AsyncMock 桩,供
|
||
需要端口依赖的测试按需调用。
|
||
|
||
桩使用 ``AsyncMock()``,预设主要方法返回值,调用方可按需覆盖。方法签名
|
||
以 ``WecomClient`` 实现为准。单文件独有的 helper 应保留在对应测试文件内
|
||
(见 testing-guidelines.md)。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from unittest.mock import AsyncMock
|
||
|
||
import pytest
|
||
|
||
from yuxi.channels.contract.dtos.option import Nothing
|
||
|
||
|
||
@pytest.fixture
|
||
def fake_wecom_client() -> AsyncMock:
|
||
"""WecomClient 桩。
|
||
|
||
``AsyncMock()`` 模拟 ``WecomClient``,预设主要方法返回值:
|
||
- ``send_message`` / ``send_kf_message`` / ``recall_message`` /
|
||
``update_template_card`` 返回 ``{"msgid": "msg-1", "errcode": 0}``;
|
||
- ``upload_media`` 返回 ``{"media_id": "media-1", "errcode": 0}``;
|
||
- ``download_media`` 返回 ``b"fake-content"``;
|
||
- ``get_access_token`` 返回 ``"fake-token"``;
|
||
- 通讯录 / 客户联系 / 客服 / OAuth API 返回 ``{}``。
|
||
"""
|
||
client = AsyncMock()
|
||
# Token 管理
|
||
client.get_access_token.return_value = "fake-token"
|
||
client.verify_token.return_value = True
|
||
client.get_token_with_credentials.return_value = ("fake-token", 7200)
|
||
# 应用消息 API
|
||
client.send_message.return_value = {"msgid": "msg-1", "errcode": 0}
|
||
client.recall_message.return_value = {"msgid": "msg-1", "errcode": 0}
|
||
client.update_template_card.return_value = {"msgid": "msg-1", "errcode": 0}
|
||
# 资源上传/下载
|
||
client.upload_media.return_value = {"media_id": "media-1", "errcode": 0}
|
||
client.download_media.return_value = b"fake-content"
|
||
# 通讯录 API
|
||
client.get_user.return_value = {}
|
||
client.list_user_ids.return_value = {}
|
||
client.convert_to_openid.return_value = {}
|
||
# 客户联系 API
|
||
client.get_external_contact.return_value = {}
|
||
client.list_external_contacts.return_value = {}
|
||
client.list_group_chats.return_value = {}
|
||
client.get_group_chat.return_value = {}
|
||
client.unionid_to_external_userid.return_value = {}
|
||
# 微信客服 API
|
||
client.send_kf_message.return_value = {"msgid": "msg-1", "errcode": 0}
|
||
client.list_kf_accounts.return_value = {}
|
||
# OAuth API
|
||
client.get_oauth_user_info.return_value = {}
|
||
client.get_user_detail.return_value = {}
|
||
client.get_oauth_user_info_with_credentials.return_value = {}
|
||
client.get_user_detail_with_credentials.return_value = {}
|
||
# 其它
|
||
client.get_api_domain_ip.return_value = {}
|
||
return client
|
||
|
||
|
||
def _make_cache(get_value=None) -> AsyncMock:
|
||
"""构造 CachePort 桩。
|
||
|
||
Args:
|
||
get_value: ``get`` 方法的返回值,默认为 ``Nothing()``。传入 ``Some(...)``
|
||
可模拟命中缓存。
|
||
|
||
Returns:
|
||
AsyncMock 模拟 ``CachePort``,``get`` 默认返回 ``Nothing()``,
|
||
``set`` / ``delete`` 等方法为无返回值的 AsyncMock。
|
||
"""
|
||
cache = AsyncMock()
|
||
cache.get.return_value = Nothing() if get_value is None else get_value
|
||
cache.set.return_value = None
|
||
cache.delete.return_value = None
|
||
return cache
|
||
|
||
|
||
def _make_logger() -> AsyncMock:
|
||
"""构造 LoggerPort 桩。
|
||
|
||
Returns:
|
||
AsyncMock 模拟 ``LoggerPort``,``debug`` / ``info`` / ``warning`` /
|
||
``error`` 等方法为无返回值的 AsyncMock。
|
||
"""
|
||
logger = AsyncMock()
|
||
logger.debug.return_value = None
|
||
logger.info.return_value = None
|
||
logger.warning.return_value = None
|
||
logger.error.return_value = None
|
||
return logger
|
||
|
||
|
||
def _make_config(config_value=None) -> AsyncMock:
|
||
"""构造 ConfigPort 桩。
|
||
|
||
Args:
|
||
config_value: ``get`` 方法返回的 ConfigValue mock。默认构造一个带
|
||
``.value`` 属性的 mock,调用方可传入自定义 mock 覆盖。
|
||
|
||
Returns:
|
||
AsyncMock 模拟 ``ConfigPort``,``get`` 默认返回带 ``.value`` 的
|
||
ConfigValue mock。
|
||
"""
|
||
config = AsyncMock()
|
||
if config_value is None:
|
||
cv = AsyncMock()
|
||
cv.value = None
|
||
config.get.return_value = cv
|
||
else:
|
||
config.get.return_value = config_value
|
||
return config
|