diff --git a/nonebot/internal/adapter/bot.py b/nonebot/internal/adapter/bot.py index 8961b89f..3f827b18 100644 --- a/nonebot/internal/adapter/bot.py +++ b/nonebot/internal/adapter/bot.py @@ -106,7 +106,10 @@ class Bot(abc.ABC): logger.debug("Running CalledAPI hooks...") await asyncio.gather(*coros) except MockApiException as e: + # mock api result result = e.result + # ignore exception + exception = None logger.debug( f"Calling API {api} result is mocked. Return {result} instead." ) diff --git a/tests/test_adapters/test_bot.py b/tests/test_adapters/test_bot.py new file mode 100644 index 00000000..76571470 --- /dev/null +++ b/tests/test_adapters/test_bot.py @@ -0,0 +1,152 @@ +from typing import Any, Dict, Optional + +import pytest +from nonebug import App + +from nonebot.adapters import Bot +from nonebot.exception import MockApiException + + +@pytest.mark.asyncio +async def test_bot_call_api(app: App): + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, True) + result = await bot.call_api("test") + + assert result is True + + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, exception=RuntimeError("test")) + with pytest.raises(RuntimeError, match="test"): + await bot.call_api("test") + + +@pytest.mark.asyncio +async def test_bot_calling_api_hook_simple(app: App): + runned: bool = False + + async def calling_api_hook(bot: Bot, api: str, data: Dict[str, Any]): + nonlocal runned + runned = True + + hooks = set() + + with pytest.MonkeyPatch.context() as m: + m.setattr(Bot, "_calling_api_hook", hooks) + + Bot.on_calling_api(calling_api_hook) + + assert hooks == {calling_api_hook} + + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, True) + result = await bot.call_api("test") + + assert runned is True + assert result is True + + +@pytest.mark.asyncio +async def test_bot_calling_api_hook_mock(app: App): + runned: bool = False + + async def calling_api_hook(bot: Bot, api: str, data: Dict[str, Any]): + nonlocal runned + runned = True + + raise MockApiException(False) + + hooks = set() + + with pytest.MonkeyPatch.context() as m: + m.setattr(Bot, "_calling_api_hook", hooks) + + Bot.on_calling_api(calling_api_hook) + + assert hooks == {calling_api_hook} + + async with app.test_api() as ctx: + bot = ctx.create_bot() + result = await bot.call_api("test") + + assert runned is True + assert result is False + + +@pytest.mark.asyncio +async def test_bot_called_api_hook_simple(app: App): + runned: bool = False + + async def called_api_hook( + bot: Bot, + exception: Optional[Exception], + api: str, + data: Dict[str, Any], + result: Any, + ): + nonlocal runned + runned = True + + hooks = set() + + with pytest.MonkeyPatch.context() as m: + m.setattr(Bot, "_called_api_hook", hooks) + + Bot.on_called_api(called_api_hook) + + assert hooks == {called_api_hook} + + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, True) + result = await bot.call_api("test") + + assert runned is True + assert result is True + + +@pytest.mark.asyncio +async def test_bot_called_api_hook_mock(app: App): + runned: bool = False + + async def called_api_hook( + bot: Bot, + exception: Optional[Exception], + api: str, + data: Dict[str, Any], + result: Any, + ): + nonlocal runned + runned = True + + raise MockApiException(False) + + hooks = set() + + with pytest.MonkeyPatch.context() as m: + m.setattr(Bot, "_called_api_hook", hooks) + + Bot.on_called_api(called_api_hook) + + assert hooks == {called_api_hook} + + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, True) + result = await bot.call_api("test") + + assert runned is True + assert result is False + + runned = False + + async with app.test_api() as ctx: + bot = ctx.create_bot() + ctx.should_call_api("test", {}, exception=RuntimeError("test")) + result = await bot.call_api("test") + + assert runned is True + assert result is False