为什么Python单元测试中GetDatabaseConnection类没有被成功mock?
问题根因
你将数据库连接、密钥拉取等IO逻辑直接写在了GetDatabaseConnection的类属性定义阶段,这部分代码会在Python导入lambda_function模块、解析类定义的时候就同步执行,执行时机远早于测试函数中mock逻辑的生效时间。从报错栈也可以看出,错误触发在mock的上下文初始化阶段导入模块的环节,还没有进入你编写的测试函数执行步骤。
解决方案
方案1:优化业务代码(推荐)
将类属性的初始化逻辑迁移到实例构造方法__init__中,避免模块导入阶段执行IO操作,修改后的类定义如下:
class GetDatabaseConnection: def __init__(self): resp_dict = json.loads(get_secret()) self.endpoint = resp_dict.get('host') self.username = resp_dict.get('username') self.password = resp_dict.get('password') self.database_name = resp_dict.get('dbname') self.port = resp_dict.get('port') self.connection = pymysql.connect( host=self.endpoint, user=self.username, passwd=self.password, db=self.database_name, port=self.port ) self.cursor = self.connection.cursor()
修改完成后你原有测试代码的mock逻辑即可正常生效,因为此时连接逻辑只会在GetDatabaseConnection类实例化的时候才会执行,此时mock替换已经完成。
方案2:不修改业务代码,调整测试逻辑
如果无法修改业务代码,需要在导入lambda_function模块之前先mock掉类定义依赖的get_secret和pymysql.connect方法,示例测试代码如下:
from unittest import mock # 先mock依赖再导入业务模块 with mock.patch("lambda_function.get_secret", return_value='{"host":"test","username":"test","password":"test","dbname":"test","port":3306}'): with mock.patch("lambda_function.pymysql.connect"): from lambda_function import GetDatabaseConnection @mock.patch("lambda_function.GetDatabaseConnection") def test_mock_simple_class(mock_class): mock_class.return_value = "test" # 后续测试逻辑
注意事项
如果你的业务代码中直接调用了GetDatabaseConnection的类属性(比如GetDatabaseConnection.cursor),需要为mock对象补充对应的属性定义,避免运行时报属性不存在的错误。
内容的提问来源于stack exchange,提问作者L44TXF
相关产品推荐
相关产品推荐

