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

如何使用patch和autospec模拟带有嵌套属性的类?

如何用patch和autospec递归模拟带属性的类?

我想了解是否可以通过patch和autospec模拟包含属性的类?以下示例的目标是递归模拟ClassB。

示例代码

class_c.py

class ClassC:
    def get_default(self) -> list[int]:
        return [1, 2, 3]

    def delete(self, name: str):
        print(f"delete {name}")

class_b.py

from class_c import ClassC

class ClassB:
    def __init__(self) -> None:
        self._ds = ClassC()

    @property
    def class_c(self) -> ClassC:
        return self._ds

    def from_config(self, cred: str) -> str:
        return cred

class_a.py

from class_b import ClassB

class ClassA:
    def __init__(self):
        self._client = ClassB()

    @property
    def class_b(self) -> ClassB:
        return self._client

    def test(self, cred: str) -> str:
        return cred

test.py

import pytest
from unittest import mock

@mock.patch("class_a.ClassB", autospec=True)
def test_class_a(_):
  class_a = ClassA()
  with pytest.raises(TypeError):
      class_a.class_b.from_config()  # ✅ 触发异常 - 缺少必填参数cred
  with pytest.raises(TypeError):
      class_a.class_b.class_c.delete()  # <- ❌ 问题所在 - 按autospec=True预期应该触发TypeError,但实际未生效

ClassB的class_c属性未被正确模拟,我期望调用delete()不传参数时触发TypeError,但目前未生效。尝试多种方法都未成功,请问有解决思路吗?

编辑1:
上述代码仅为示例,测试函数用于展示预期行为,ClassB可视为需模拟的第三方服务。

编辑2:
除已采纳的解决方案外,建议使用PropertyMock模拟属性:

def test_class_a():
    class_b_mock = create_autospec(class_a.ClassB)
    class_c_mock = create_autospec(class_b.ClassC)
    type(class_b).class_c = PropertyMock(return_value=class_c_mock)
    with mock.patch("class_a.ClassB", return_value=class_b_mock):
        class_a_instance = ClassA()
        with pytest.raises(TypeError):
            class_a_instance.class_b.from_config()
        with pytest.raises(TypeError):
            class_a_instance.class_b.class_c.delete()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:40:27