如何用Pytest测试含参数Discord Bot的on_command_error异常消息发送
问题:测试带参数Discord命令的错误处理逻辑失败
我在编写Pytest单元测试,验证Discord Bot的错误处理逻辑:当调用带必填参数的命令且未加载游戏时,触发CommandInvokeError后,on_command_error()需要发送「Game not loaded....」提示消息。
无参数命令的测试用invoke(ctx)能正常通过,但带参数的log命令尝试用invoke(ctx, words=10)时会触发TypeError;尝试直接调用命令方法、使用callback或手动dispatch事件,都无法通过断言——Bot实际运行正常,但测试始终失败。
问题分析
invoke()方法参数错误:Discord.py的Command.invoke()方法不支持直接传入命令参数(比如words=10),它依赖解析ctx.message.content来获取参数,直接传参会触发类型错误。- 错误链不匹配:
on_command_error()的判断条件要求err.__cause__是AttributeError且self.game为None,若测试中触发的错误不符合这个链,断言就会失败。
解决方案
方法一:模拟命令消息,让Discord.py自动解析参数
通过设置ctx.message.content模拟用户发送的命令消息,让invoke()方法正常解析参数,触发预期的错误链:
@pytest.mark.asyncio async def test_submit_words_no_game( bot: client.WordDebtBot, player: game_lib.WordDebtPlayer ): ctx = AsyncMock() ctx.author.id = player.user_id # 模拟用户发送的命令消息,包含前缀和参数 ctx.message.content = "!log 10" ctx.prefix = "!" game_cmds_cog = bot.get_cog("Core Gameplay Module") cmd_err_cog = bot.get_cog("Command Error Handler") game_cmds_cog.game = None cmd_err_cog.game = None with pytest.raises(commands.CommandInvokeError) as err_info: await game_cmds_cog.log.invoke(ctx) # 调用错误处理方法 await cmd_err_cog.on_command_error(ctx, err_info.value) # 断言消息发送正确 ctx.send.assert_called_with("Game not loaded....")
方法二:直接调用命令callback,手动构造错误对象
如果不想依赖命令解析逻辑,可以直接调用命令的callback方法,捕获AttributeError后,手动封装成CommandInvokeError传给错误处理器:
@pytest.mark.asyncio async def test_submit_words_no_game( bot: client.WordDebtBot, player: game_lib.WordDebtPlayer ): ctx = AsyncMock() ctx.author.id = player.user_id game_cmds_cog = bot.get_cog("Core Gameplay Module") cmd_err_cog = bot.get_cog("Command Error Handler") game_cmds_cog.game = None cmd_err_cog.game = None try: # 直接调用命令的callback方法,触发AttributeError await game_cmds_cog.log.callback(game_cmds_cog, ctx, words=10) except AttributeError as attr_err: # 封装成符合要求的CommandInvokeError invoke_err = commands.CommandInvokeError(attr_err) # 调用错误处理逻辑 await cmd_err_cog.on_command_error(ctx, invoke_err) # 断言消息发送正确 ctx.send.assert_called_with("Game not loaded....")
关键说明
- 方法一更贴近真实用户场景,测试命令解析和错误处理的完整流程
- 方法二更聚焦错误处理逻辑本身,跳过命令解析环节,适合单独验证错误处理器的判断逻辑
内容的提问来源于stack exchange,提问作者Gregory Nitch
相关产品推荐
相关产品推荐

