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

如何使用pytest-mock模拟带@property装饰器的Python类属性?

问题描述

我尝试使用pytest-mock模拟Python类,但始终未能掌握正确方法。我有一个Model类,其objects属性(带@property装饰器)返回模型内Line、Square、Circle等不同对象的列表。由于Model需读取大文件生成且在应用中多处使用,我希望通过mock验证功能逻辑。我尝试了以下测试代码:

def test_parse_find_elements_by_name(parser, mocker):
    def mock_objects(self):
        return ["a","b","c"]
    model = Model()
    mocker.patch( "orcaflow.Model.objects", mock_objects )
    assert model.objects == ["a", "b", "c"]

但该代码返回的是方法而非属性。目前我通过直接使用mock包实现了临时解决方案:

@pytest.fixture
def mocked_model(mocker):
    objects = []
    for i in range(10):
        obj = MagicMock()
        obj.name = "Line %d" % i
        objects.append(obj)
    model = Mock(objects = objects )
    return model

请问是否有直接使用pytest-mock实现的更优方案?

解决方案

我明白你遇到的问题了——用pytest-mock模拟带@property装饰器的类属性确实容易踩坑,你之前的代码之所以返回方法而非属性,是因为没有正确处理@property的特性:直接把普通函数patch给属性位,Python会把它当成未绑定的方法,而非属性的返回值。下面给你两种更优雅的pytest-mock实现方案:

方案1:使用mocker.patch_property(推荐)

pytest-mock的patch_property方法是专门为模拟类属性设计的,用法非常直观:

def test_parse_find_elements_by_name(mocker):
    # 定义你想让objects返回的模拟数据
    mock_objects_list = ["a", "b", "c"]
    # 直接patch Model类的objects属性,指定返回值
    mocker.patch_property(orcaflow.Model, "objects", return_value=mock_objects_list)
    
    model = orcaflow.Model()
    assert model.objects == ["a", "b", "c"]  # 现在能正确拿到属性值了

方案2:将mock函数包装为property再patch

如果你更习惯用基础的patch方法,只需要把你的mock函数包装成property类型即可:

def test_parse_find_elements_by_name(mocker):
    def mock_objects(self):
        return ["a", "b", "c"]
    # 把mock函数转为property后再patch
    mocker.patch("orcaflow.Model.objects", property(mock_objects))
    
    model = orcaflow.Model()
    assert model.objects == ["a", "b", "c"]

优化你的Fixture方案

针对你现有的临时Fixture,也可以用pytest-mock改造得更贴近真实场景(返回真实的Model实例而非Mock对象):

@pytest.fixture
def mocked_model(mocker):
    objects = []
    for i in range(10):
        obj = mocker.MagicMock()  # 直接用pytest-mock提供的MagicMock
        obj.name = f"Line {i}"
        objects.append(obj)
    # 用patch_property模拟objects属性
    mocker.patch_property(orcaflow.Model, "objects", return_value=objects)
    # 返回真实的Model实例,这样测试逻辑和生产环境的调用方式完全一致
    return orcaflow.Model()

这样改造后,你的测试用例可以直接使用mocked_model fixture,访问它的objects属性就能得到你预设的模拟对象列表,既保留了真实实例的结构,又避免了读取大文件的开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:36:49