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

Python unittest mock报AttributeError找不到extract属性排查

报错根因

两个版本代码报错核心来自三个问题:

  • 初始版本mock目标错误:extract是DataExtractor类的实例方法,不属于Task类,对workflow.workflow.Task.extract打补丁必然触发属性不存在的错误。
  • 测试目标偏离:你要验证的是Task.extract_data的逻辑,更新后的测试代码直接实例化DataExtractor调用extract,完全没有覆盖Task类的业务逻辑。
  • 业务代码存在语法错误:更新后的workflow.py中extract_data方法里key=key引用了未定义的变量,运行会直接抛出NameError;初始版本直接用类调用实例方法Task.extract_data()也会因缺少self参数报错。
正确mock实现方案

Python mock的核心规则是在哪用,在哪patch:你在workflow.workflow模块中导入并使用了DataExtractor,直接patch这个模块下的DataExtractor引用即可。

第一步:修复业务代码语法问题

先修正workflow.py的未定义变量问题,调整后代码如下:

# src/workflow/workflow.py
from data_extractor.data_extractor import DataExtractor

class Task:
    def __init__(self, task_type: str, name: str, key: str) -> None:
        self.name = name
        self.task_type = task_type
        self.key = key
        self.extractor = DataExtractor()

    def extract_data(self):
        # key从实例属性获取,避免未定义错误
        obj = self.extractor.extract(name=self.name, key=self.key)
        return obj

第二步:编写正确的单元测试

测试逻辑围绕Task.extract_data展开,验证方法调用时底层依赖的行为符合预期,调整后测试代码如下:

# tests/test_extract.py
import unittest
from unittest import mock
from workflow.workflow import Task


class TestTaskExtract(unittest.TestCase):
    @mock.patch("workflow.workflow.DataExtractor")
    def test_extract_from_snowflake(self, mock_data_extractor):
        # 配置mock返回值:模拟extractor.extract的返回结果
        mock_extractor_instance = mock_data_extractor.return_value
        mock_extractor_instance.extract.return_value = [{"id": 1, "value": "test"}]

        # 实例化Task,调用待测试的目标方法
        test_task = Task(task_type="snowflake", name="entities", key="11")
        actual_result = test_task.extract_data()

        # 校验返回值符合预期
        self.assertEqual(actual_result, [{"id": 1, "value": "test"}])
        # 校验DataExtractor被正确实例化
        mock_data_extractor.assert_called_once_with()
        # 校验extract方法被传入正确参数调用
        mock_extractor_instance.extract.assert_called_once_with(name="entities", key="11")


if __name__ == "__main__":
    unittest.main()
常见mock踩坑提醒
  • 实例方法必须通过类实例调用:直接写Task.extract_data()属于错误用法,会因为缺少绑定的self参数抛出异常。
  • 不要乱改patch路径:不需要patchdata_extractor.data_extractor.DataExtractor,因为workflow模块已经把DataExtractor导入到自身命名空间,你要替换的是workflow模块下的这个引用。
  • 断言要匹配正确的mock对象:装饰器注入的mock_data_extractor对应DataExtractor类本身,用来校验实例化逻辑;mock_data_extractor.return_value对应实例化后的extractor对象,它的extract方法才是需要校验入参的目标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:30:48