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

如何Mock类实例属性?Mock Meta.metadata触发AttributeError问题排查

如何Mock类的实例属性(而非类属性)

我之前成功Mock过类函数,但无法Mock类的实例属性。以下是目标类代码:

# 文件路径:exchanges.exchange
class Meta:
    required_fields = ['security_file', 'data_file_group', 'mic']

    def __init__(self, exchange):
        self.exchange = exchange
        self.metadata = {}  # 证券代码到元数据字典的映射
        self.db_write = exchange.db_write

我需要Mock上述代码中的self.metadata属性,于是在测试代码中编写了如下内容:

@mock.patch('exchanges.exchange.Meta.metadata', return_value =
    {('10080', '20230104'): {'price_type': 'U', 'isin': 
      'data_file_group': 'itchebbo', 'security_file': '10080_20230104.h5'}})
def test_check_valid_currency_no_ccy_no_Bloomberg():
    # 测试逻辑...

运行测试时触发错误:

AttributeError: <class 'exchanges.exchange.Meta'> does not have the attribute 'metadata'

我疑惑mock.patch是否仅适用于Mock函数和类,而非类实例属性,希望能成功Mock Meta的metadata实例属性。


问题原因

你当前的写法是试图Mock类属性Meta.metadata,但metadata是在__init__方法中定义的实例属性——类本身并没有这个属性,只有类的实例才会在初始化后拥有该属性,因此报错。

解决方案

针对实例属性的Mock需要在实例层面操作,以下是几种可行方法:

方法1:直接替换实例属性

如果测试代码中会主动创建Meta实例,初始化后直接替换其metadata属性即可:

def test_check_valid_currency_no_ccy_no_Bloomberg():
    # 创建exchange的Mock对象(满足Meta初始化参数要求)
    mock_exchange = Mock()
    # 初始化Meta实例
    meta_instance = Meta(mock_exchange)
    # 替换实例的metadata为预设值
    meta_instance.metadata = {
        ('10080', '20230104'): {
            'price_type': 'U', 
            'isin': '', 
            'data_file_group': 'itchebbo', 
            'security_file': '10080_20230104.h5'
        }
    }
    # 执行后续测试逻辑
    # ...

方法2:Mock__init__方法预设属性

如果希望实例创建时自动带有预设的metadata,可以Mock类的__init__方法,手动模拟属性赋值:

@mock.patch('exchanges.exchange.Meta.__init__')
def test_check_valid_currency_no_ccy_no_Bloomberg(mock_init):
    mock_exchange = Mock()
    # 自定义__init__的执行逻辑
    def init_side_effect(exchange):
        self = mock_init.return_value
        self.exchange = exchange
        # 直接设置预设的metadata
        self.metadata = {
            ('10080', '20230104'): {
                'price_type': 'U', 
                'isin': '', 
                'data_file_group': 'itchebbo', 
                'security_file': '10080_20230104.h5'
            }
        }
        self.db_write = exchange.db_write
    mock_init.side_effect = init_side_effect

    # 创建实例,此时metadata已被预设
    meta_instance = Meta(mock_exchange)
    # 执行测试逻辑
    # ...

方法3:用patch.object替换已有实例的属性

如果被测试代码中已经存在Meta实例,可通过patch.object临时替换其metadata:

def test_check_valid_currency_no_ccy_no_Bloomberg():
    # 假设被测试代码中已有一个Meta实例target_meta
    target_meta = Meta(Mock())
    # 上下文管理器中替换属性
    with mock.patch.object(target_meta, 'metadata', new={
        ('10080', '20230104'): {
            'price_type': 'U', 
            'isin': '', 
            'data_file_group': 'itchebbo', 
            'security_file': '10080_20230104.h5'
        }
    }):
        # 此上下文中target_meta的metadata为预设值
        # 执行测试逻辑
        # ...

总结

mock.patch并非只能Mock函数和类,关键是要区分类属性和实例属性:类属性直接属于类,而实例属性仅存在于类的实例中。针对实例属性的Mock,需要在实例创建后操作,或通过Mock初始化方法来预设属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:47:07