Django单元测试mock.patch无法正确mock依赖类属性的解决方法
Django单元测试mock.patch不生效解决方法
核心规则
mock.patch 必须patch被测模块中实际使用的依赖引用,而非依赖本身的定义路径;同时patch.object仅支持指定目标对象的直接属性名,不支持点分隔的嵌套路径。
之前写法的错误原因
- 直接patch
CctSerializer.data不生效:data是序列化器实例的动态属性,类层面的属性patch会被实例初始化逻辑覆盖,无法作用到getAll()函数内部新建的序列化器实例。 @mock.patch.object(CctDAO, 'CctSerializer.data', ...)报错:patch.object的第二个参数只能传目标对象的直接属性名,CctDAO模块下只有CctSerializer属性,不存在名为CctSerializer.data的直接属性,因此抛出属性不存在错误。- 注释掉的
CCT.objects.allpatch路径本身正确,未生效通常是因为未配置return_value,或是模块路径大小写拼写错误(贴出的代码中存在MyApp/Myapp两种大小写写法,Python模块导入大小写敏感,路径错误会直接导致mock失效)。
正确写法示例
方案1:Mock数据库查询层(推荐)
直接patch CctDAO模块内引用的CCT模型的查询方法,不需要修改序列化逻辑,更贴近真实业务执行流程:
from unittest import TestCase, mock from .DataAccessLayer import CctDAO class Test_CCT_DAO(TestCase): # 注意路径是CctDAO模块下导入的CCT,不是models文件中定义的CCT @mock.patch('apps.MyApp.DataAccessLayer.CctDAO.CCT.objects.all') def test_getall_empty(self, mock_cct_all): # 空数据场景 mock_cct_all.return_value = [] self.assertEqual([], CctDAO.getAll()) # 带数据场景 mock_cct_all.return_value = ['mock_entity_1', 'mock_entity_2'] # 此处会走真实序列化逻辑,如果需要跳过序列化可以搭配方案2使用
方案2:Mock序列化器返回值
如果不需要验证序列化逻辑,可以直接patch序列化器类,手动指定data属性的返回值:
from unittest import TestCase, mock from .DataAccessLayer import CctDAO class Test_CCT_DAO(TestCase): @mock.patch('apps.MyApp.DataAccessLayer.CctDAO.CctSerializer') def test_getall_mock_data(self, mock_serializer_cls): # 配置mock序列化器实例的返回值 mock_serializer = mock.Mock() mock_serializer.data = ['mocked-data1'] # 让CctSerializer()实例化时返回我们配置的mock对象 mock_serializer_cls.return_value = mock_serializer result = CctDAO.getAll() self.assertEqual(['mocked-data1'], result) # 可选:验证序列化器是否按预期参数调用 mock_serializer_cls.assert_called_once_with(mock.ANY, many=True)
注意:请确保patch路径的大小写和实际文件路径完全一致,路径拼写错误是mock不生效的高频原因。
内容的提问来源于stack exchange,提问作者Sportalcraft
相关产品推荐
相关产品推荐

