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

在Python unittest中如何获取被Mock方法调用的FooBar实例?

Python unittest中Mock子类继承方法并调用实例自身方法的解决方案

原代码结构

class Foo:
   def start(self):
     # do something

class FooBar(Foo):
   def __init__(self, param):
     self.param = param

   def run(self):
     # do something else

class ProductionClass:
   def use_foobar(self):
     foo = FooBar("string")
     foo.start()

需求与问题

需要编写测试用例,Mock FooBar继承自Foo的start方法,使其转而调用该FooBar实例自身的run方法。但之前的写法无法获取use_foobar内部创建的FooBar实例,导致无法在mock方法中调用目标方法。

尝试的代码

def test_something(self):
    self.foobar_patcher = patch.object(FooBar, 'start', side_effect=self.mock_start)
    self.foobar_patcher.start()

    ProductionClass().use_foobar()

def mock_start(self):
    the_production_class_instance.run()

解决方案

利用side_effect的特性:当为其传递函数时,该函数会接收原方法被调用时的所有参数,包括实例自身(即原方法的self参数)。只需修改mock方法,接收实例参数并调用其run即可。

修改后的测试代码

from unittest.mock import patch
import unittest

# 导入你的ProductionClass、FooBar等类

class TestProductionClass(unittest.TestCase):
    def test_something(self):
        # 定义mock方法,接收调用start的FooBar实例
        def mock_start(instance):
            instance.run()
        
        # 为FooBar的start方法打补丁
        with patch.object(FooBar, 'start', side_effect=mock_start):
            ProductionClass().use_foobar()
    
    # 用lambda简化写法的版本
    def test_something_simplified(self):
        with patch.object(FooBar, 'start', side_effect=lambda instance: instance.run()):
            ProductionClass().use_foobar()

验证run方法被调用的扩展写法

如果需要确认run方法确实被触发,可以额外Mockrun并添加断言:

def test_run_called(self):
    with patch.object(FooBar, 'run') as mock_run:
        def mock_start(instance):
            instance.run()
        
        with patch.object(FooBar, 'start', side_effect=mock_start):
            ProductionClass().use_foobar()
        
        # 断言run方法被调用一次
        mock_run.assert_called_once()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:43:37