Python:如何在导入时Mock值以实现继承类的单元测试?
解决方案:在导入前Mock依赖以修改类继承行为
这个问题的核心在于Python模块导入的特性——一旦模块被导入,它的代码就已经执行过了,所以你必须在导入pkg.models之前完成对pkg.database.db的Mock,这样Meta类才会继承你想要的declarative_base()而不是真实的db.Model。下面是具体的实现方案:
方法1:使用Python标准库unittest.mock
直接使用patch上下文管理器,确保在Mock生效后再导入目标类:
from unittest.mock import patch from sqlalchemy.ext.declarative import declarative_base def test_meta_inheritance(): # 创建测试用的base类 test_base = declarative_base() # 对pkg.database.db进行Mock with patch('pkg.database.db') as mock_db: # 把Mock对象的Model属性替换为我们的test_base mock_db.Model = test_base # 关键:必须在patch内部导入Meta,此时导入会使用Mock后的db from pkg.models import Meta # 验证继承关系 assert issubclass(Meta, test_base) # 在这里添加其他测试逻辑,比如验证字段、方法等
方法2:使用Pytest + pytest-mock
如果你用Pytest作为测试框架,可以借助pytest-mock提供的mocker fixture,写法更简洁:
from sqlalchemy.ext.declarative import declarative_base def test_meta_inheritance(mocker): test_base = declarative_base() # Mock pkg.database.db对象 mock_db = mocker.patch('pkg.database.db') mock_db.Model = test_base # 同样在Mock生效后导入Meta from pkg.models import Meta assert issubclass(Meta, test_base)
关键注意事项
- 绝对不要在测试文件顶部提前导入
pkg.models:如果在Mock之前就导入了pkg.models,Python会缓存模块内容,后续的Mock不会影响已经定义好的Meta类。 - 复用Mock逻辑:如果多个测试都需要这个Mock,可以用Pytest的fixture或者Unittest的
setUp方法封装:import pytest from sqlalchemy.ext.declarative import declarative_base from unittest.mock import patch @pytest.fixture def mocked_meta(): test_base = declarative_base() with patch('pkg.database.db') as mock_db: mock_db.Model = test_base from pkg.models import Meta yield Meta, test_base def test_meta_fields(mocked_meta): Meta, test_base = mocked_meta # 测试Meta的字段定义等 assert hasattr(Meta, 'id')
内容的提问来源于stack exchange,提问作者jpala
相关产品推荐
相关产品推荐

