如何Mock pymysqlpool.ConnectionPool构造函数?测试仍触发连接错误
问题解决:Mock pymysqlpool.ConnectionPool无效导致实际连接数据库
错误原因
你当前的@mock.patch('pymysqlpool.ConnectionPool')路径不对。Python的mock遵循**“在哪里使用就patch哪里”的原则:如果测试代码里直接从pymysqlpool导入ConnectionPool,需要patch的是测试模块自身中的ConnectionPool引用**,而非原库中的类。直接patch原库路径不会替换测试代码里已导入的类引用,导致实际构造函数仍被执行,触发数据库连接错误。
解决方案
1. 修正patch路径
假设你的测试文件名为test_db.py,且测试代码里是from pymysqlpool import ConnectionPool,把patch目标改成测试模块内的ConnectionPool:
@mock.patch(__name__ + '.ConnectionPool', autospec=True)
或者直接写模块名:
@mock.patch('test_db.ConnectionPool', autospec=True)
如果是测试业务代码(比如业务代码在myapp/db.py中导入并使用ConnectionPool),则需要patch业务模块中的引用:
@mock.patch('myapp.db.ConnectionPool', autospec=True)
2. 验证Mock是否生效(可选但推荐)
在测试方法中添加断言,确认Mock的构造函数被正确调用:
def test_load(self, connection_pool_mock: mock.Mock): ConnectionPool( size=2, maxsize=3, pre_create_num=2, host=os.environ["DATASOURCES_0_HOST"] ) # 验证构造参数是否正确传递 connection_pool_mock.assert_called_once_with( size=2, maxsize=3, pre_create_num=2, host="non-existent" )
修改后的完整测试代码
class DbTests(TestCase): @mock.patch(__name__ + '.ConnectionPool', autospec=True) @mock.patch.dict( os.environ, { "DATASOURCES_0_SERVERID": "server1", "DATASOURCES_0_HOST": "non-existent", "DATASOURCES_0_PORT": "3307", "DATASOURCES_0_DATABASE": "lj_ca1", "DATASOURCES_0_USERNAME": "sampleuser", "DATASOURCES_0_PASSWORD": "password1", "DATASOURCES_0_TIMEZONE": "Americas/Toronto", }, ) def test_load(self, connection_pool_mock: mock.Mock): ConnectionPool( size=2, maxsize=3, pre_create_num=2, host=os.environ["DATASOURCES_0_HOST"] ) # 断言Mock被正确调用 connection_pool_mock.assert_called_once_with( size=2, maxsize=3, pre_create_num=2, host="non-existent" )
关键原理
Python的import会把模块中的对象引用缓存到导入者的命名空间里。你之前patch的是原库pymysqlpool中的ConnectionPool类,但测试代码里已经导入了该类的引用,这个引用不会因为原库的类被patch而改变。只有patch测试代码(或业务代码)命名空间里的那个ConnectionPool引用,才能替换掉实际使用的构造函数。
内容的提问来源于stack exchange,提问作者Archimedes Trajano
相关产品推荐
相关产品推荐

