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

Python3中如何mock配置变量实现无需AWS凭证运行单元测试?

问题根因

报错的核心原因是模块导入阶段就已经触发了AWS SSM调用:你在测试代码顶部直接写from service import send_mail时,Python会先执行service.py的导入逻辑,加载configs模块,而configs.py里的load_parameters是模块级顶层代码,会在导入时直接执行,这时候你的mock逻辑还没有运行,自然会触发AWS凭证校验报错。你后续mockservice.SENDER这类变量的时候,SSM调用已经执行完成,所以mock不会生效。


解决方案

方案1:无需修改业务代码,调整测试逻辑即可快速解决

调整测试代码的导入顺序,先mock掉SSM参数加载逻辑,再导入业务模块:

# test_service.py
from unittest import TestCase, main, mock

class TestMailService(TestCase):
     def test_service(self):
       # 第一步:先mock configs模块的SSM参数加载方法
       with mock.patch('configs.load_parameters') as mock_load:
           # 给mock配置不同参数对应的返回值
           mock_load.side_effect = lambda param_name: {
               # 填入你实际参数路径对应的测试返回值
               "/your/path/mail_sender": "abc@sys.com",
               "/your/path/mail_destinations": "def@sys.com",
               # 其他configs中需要加载的参数都可以在这里配置返回值
           }.get(param_name, "mock_default_value")
           
           # 第二步:mock完成后再导入service模块,此时导入不会触发真实SSM调用
           from service import send_mail
           
           with mock.patch('service.logging.Logger.info') as mocked_logging:
              send_mail(...)
              mocked_logging.assert_called_with('mail sent Successfully')

if __name__ == "__main__":
    main()

如果有多个测试用例需要复用mock,可以把mock逻辑放到setUp()方法中提前执行即可。


方案2:重构配置加载逻辑,从根源提升可测试性(长期最优方案)

把configs.py的模块级参数加载逻辑改成懒加载,避免导入时直接触发SSM调用:

# configs.py 重构后
from handlers.ssm_handler import load_parameters
from common import constants
import os
environment = os.environ.get(constants.ENVIRONMENT)

# 改为调用时才加载参数
def get_config(config_key):
    param_path_map = {
        "JSON_BUCKET": constants.OT_ARCHIVAL_PREFIX+environment+constants.MIGRATION_BUCKET,
        "SENDER": constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_SENDER,
        "DESTINATIONS": constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_DESTINATIONS,
    }
    return load_parameters(param_path_map[config_key])

调整service.py的参数获取方式:

#service.py 重构后
from configs import get_config
from constants import LOG_FORMAT
import logging

def send_mail(body):
    SENDER = get_config("SENDER")
    DESTINATIONS = get_config("DESTINATIONS")
    ...

调整后测试代码可以直接在顶部导入业务模块,只需要mockget_config方法即可,不需要处理导入顺序:

# 重构后的test_service.py
from unittest import TestCase, main, mock
from service import send_mail

class TestMailService(TestCase):
     @mock.patch('service.get_config')
     @mock.patch('service.logging.Logger.info')
     def test_service(self, mocked_logging, mock_get_config):
         # 配置get_config的返回值
         mock_get_config.side_effect = lambda key: {
             "SENDER": "abc@sys.com",
             "DESTINATIONS": "def@sys.com"
         }.get(key)
         
         send_mail(...)
         mocked_logging.assert_called_with('mail sent Successfully')

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

相关产品推荐
方舟 Agent Plan

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

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