You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中Mock类方法调用的跨模块sendemail方法?

解决Mock跨模块sendemail方法的路径问题

你的问题核心是Mock路径错误,当前@patch("app.config.parse_config.logger.critical.sendemail")完全不符合实际调用逻辑。要正确Mock,必须遵循Mock被调用代码所在模块中导入的目标对象这一核心原则。

调用链分析

  1. parse_config.py中调用的logger.critical(),其logger是基于CwLogger类的实例
  2. CwLogger.critical()方法内部直接调用的sendemail函数,是从app.utils.sendemail导入到app.utils.logging模块中的引用
  3. 你需要Mock的是app.utils.logging模块内的sendemail引用,而非logger.critical下的子属性(该属性根本不存在)

修正后的测试代码

将patch路径改为app.utils.logging.sendemail,修改后的测试方法如下:

@patch.dict(os.environ, {"AWS_REGION": region, "CW_MODE": mode})
@patch('app.config.parse_config.get_from_ssm')
@patch('app.config.parse_config.process_queue')
@patch("app.utils.logging.sendemail")  # 正确的Mock路径
def test_parse_args_no_mandatory(self, mock_sendmail, mock_process_queue, mock_get_from_ssm):
    mock_get_from_ssm.side_effect = ["x", "y"]
    tmp_config = copy.deepcopy(good_min_config)
    mock_sendmail.return_value = None
    del tmp_config["username"]
    mock_process_queue.return_value = tmp_config

    with pytest.raises(SystemExit) as pytest_wrapped_e:
        parse_config()

    self.assertEqual(SystemExit, pytest_wrapped_e.type)
    self.assertEqual("config option: username not supplied", pytest_wrapped_e.value.code)
    # 可选:验证sendemail是否被正确触发
    mock_sendmail.assert_called_once()

关键原理说明

Python的Mock是通过替换模块命名空间中的对象生效的。CwLogger.critical里调用的sendemail,是app.utils.logging模块中导入的函数引用,必须针对这个引用的路径做Mock——而非从调用者parse_config的角度找路径,也不建议直接Mock原函数的定义路径(虽偶能生效,但针对使用场景的引用Mock更可靠)。

内容的提问来源于stack exchange,提问作者JobyB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:03:09