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

如何在Python中Mock继承的对象引用属性

如何在Python中Mock继承的对象引用属性

看起来你在测试B类的foo方法时,被继承链里的对象属性Mock难住了——没关系,我们一步步拆解问题,找到合适的Mock方式。

先分析你的调用链路:B继承自A,A的__init__里初始化了self.attr_a = C(),而B的foo方法会调用self.attr_a.session.get('model')。要让这个调用返回我们想要的测试值,我们可以在几个关键节点做Mock,下面给你几种可行的方案:

方案一:Mock C类的session属性

因为self.attr_a是C的实例,而session是C的@property,我们可以直接替换这个属性的返回值:

import unittest
from b import B
from unittest.mock import patch

class TestB(unittest.TestCase):
    def setUp(self):
        self.b = B()

    @patch('c.C.session')
    def test_foo(self, mock_session):
        # 设置mock的session返回值,让get('model')拿到'TEST'
        mock_session.return_value = {'model': 'TEST'}
        found = self.b.foo()
        expected = 'test'
        self.assertEqual(found, expected)
        # 验证session属性被访问过一次
        mock_session.assert_called_once()

解释:这里用@patch('c.C.session')替换了C类的session属性,当self.attr_a.session被访问时,会返回我们设置的{'model': 'TEST'},调用get后lower就得到了预期的'test'。

方案二:Mock A类中的attr_a实例

如果不想修改C类的行为,我们可以直接替换A类里初始化的attr_a对象,让它返回一个Mock实例:

import unittest
from b import B
from unittest.mock import patch, MagicMock

class TestB(unittest.TestCase):
    def setUp(self):
        self.b = B()

    @patch('a.A.attr_a')
    def test_foo(self, mock_attr_a):
        # 创建一个mock的session对象,让get('model')返回'TEST'
        mock_session = MagicMock()
        mock_session.get.return_value = 'TEST'
        # 让mock的attr_a的session属性返回这个mock_session
        mock_attr_a.session = mock_session
        
        found = self.b.foo()
        expected = 'test'
        self.assertEqual(found, expected)
        # 验证get方法被正确调用
        mock_session.get.assert_called_once_with('model', '')

解释:这里我们替换了A类的attr_a属性,让它变成一个Mock对象,然后给这个Mock对象的session属性绑定另一个Mock,指定get方法的返回值,这样foo里的调用就会走我们的Mock逻辑。

方案三:更细粒度Mock get方法

如果只想Mockget方法的行为,可以直接定位到session的get方法:

import unittest
from b import B
from unittest.mock import patch

class TestB(unittest.TestCase):
    def setUp(self):
        self.b = B()

    @patch('c.C.session.get')
    def test_foo(self, mock_get):
        # 设置get方法返回'TEST'
        mock_get.return_value = 'TEST'
        found = self.b.foo()
        expected = 'test'
        self.assertEqual(found, expected)
        # 验证get被调用时的参数
        mock_get.assert_called_once_with('model', '')

解释:这种方式直接Mock了session字典的get方法,不管session本身是什么,只要调用get('model', '')就会返回'TEST',适合只关注get方法行为的场景。

为什么你之前的代码没生效?

你之前的测试代码没有使用patch来替换真实的对象或方法,所以foo方法还是会访问真实的C实例的session,拿到的是真实的'modelName',lower后是'modelname',自然和预期的'test'不匹配。

另外要注意:Mock的路径很关键,必须Mock被测试代码实际访问的对象路径,比如如果B里的attr_a是从A的__init__里初始化的C实例,那么Mocka.A.attr_a是正确的;如果要MockC的session,就要Mockc.C.session,不能用错误的路径。

备注:内容来源于stack exchange,提问作者smark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:39:30