import asyncio import importlib.util import sys import types from pathlib import Path def load_sender_module(monkeypatch): """以最小 NoneBot 替身加载发送器,隔离真实 QQ 连接。""" nonebot = types.ModuleType("nonebot") nonebot.get_bots = lambda: {} nonebot.logger = types.SimpleNamespace(warning=lambda *args, **kwargs: None) adapter = types.ModuleType("nonebot.adapters.onebot.v11") class Bot: pass class Message(list): pass class MessageSegment: @staticmethod def at(qq): return ("at", qq) @staticmethod def image(image_base64): return ("image", image_base64) @staticmethod def text(text): return ("text", text) adapter.Bot = Bot adapter.Message = Message adapter.MessageSegment = MessageSegment monkeypatch.setitem(sys.modules, "nonebot", nonebot) monkeypatch.setitem(sys.modules, "nonebot.adapters.onebot.v11", adapter) path = Path(__file__).resolve().parents[1] / "danding_bot" / "plugins" / "danding_qqpush" / "sender.py" spec = importlib.util.spec_from_file_location("danding_qqpush_sender", path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def test_send_image_without_qq_does_not_add_at_segment(monkeypatch): module = load_sender_module(monkeypatch) class FakeBot: async def call_api(self, api_name, **kwargs): assert api_name == "send_group_msg" assert kwargs["group_id"] == 621016172 assert kwargs["message"] == [("image", "base64://announcement")] return {"message_id": 1} sender = module.MessageSender() sender.set_bot(FakeBot()) result = asyncio.run(sender.send_to_group(621016172, "base64://announcement")) assert result["success"] is True def test_send_image_with_qq_keeps_at_segment(monkeypatch): module = load_sender_module(monkeypatch) class FakeBot: async def call_api(self, _api_name, **kwargs): assert kwargs["message"] == [("at", 123456), ("image", "base64://announcement")] return {"message_id": 1} sender = module.MessageSender() sender.set_bot(FakeBot()) result = asyncio.run(sender.send_to_group(621016172, "base64://announcement", qq=123456)) assert result["success"] is True