Python中如何为Mock对象的属性设置side_effect?
给Mock对象的属性设置side_effect的实现方法
当然可以实现!不过属性的side_effect设置逻辑和方法不太一样,得借助unittest.mock里的PropertyMock类来搞定,我给你一步步讲清楚:
核心原理
默认情况下,当你访问Mock对象的属性(比如mock_obj.text)时,返回的是一个普通的Mock实例,它不支持side_effect。而PropertyMock是专门用来模拟类或实例属性的Mock子类,它和方法Mock一样支持side_effect和return_value参数。
具体实现步骤
1. 给已有Mock对象的属性添加side_effect
如果你已经创建了一个Mock对象,只需把目标属性替换成PropertyMock实例即可:
from unittest.mock import Mock, PropertyMock # 创建你的Mock对象 mock_obj = Mock() # 初始化PropertyMock并设置side_effect(这里用列表实现依次返回不同值) text_property = PropertyMock(side_effect=["first-text", "second-text", "third-text"]) # 将PropertyMock绑定到mock_obj的text属性上 type(mock_obj).text = text_property # 测试效果 print(mock_obj.text) # 输出: first-text print(mock_obj.text) # 输出: second-text print(mock_obj.text) # 输出: third-text
2. 配合patch装饰器使用
如果是在测试中用@patch替换真实类的属性,也可以直接指定new_callable=PropertyMock来创建带side_effect的属性Mock:
from unittest.mock import patch, PropertyMock # 假设你要替换your_module里YourClass的text属性 with patch('your_module.YourClass.text', new_callable=PropertyMock) as mock_text: # 给属性Mock设置side_effect mock_text.side_effect = ["hello", "world"] # 这里执行你的测试代码,访问YourClass().text会依次返回hello、world instance = your_module.YourClass() print(instance.text) # hello print(instance.text) # world
进阶:循环返回固定值
如果希望属性值循环往复,而不是取完列表后抛出StopIteration,可以用itertools.cycle来包装你的值列表:
from itertools import cycle from unittest.mock import Mock, PropertyMock mock_obj = Mock() # 循环返回"foo"和"bar" text_property = PropertyMock(side_effect=cycle(["foo", "bar"])) type(mock_obj).text = text_property print(mock_obj.text) # foo print(mock_obj.text) # bar print(mock_obj.text) # foo print(mock_obj.text) # bar
内容的提问来源于stack exchange,提问作者Jimmy A. León
相关产品推荐
相关产品推荐

