在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
相关产品推荐
相关产品推荐

