PyTest:如何Mock对象属性使其每次调用值变化以测试循环
问题:为属性检查循环编写单元测试时遇类型错误
被测逻辑伪代码:
def test(): while a.status != "status2": time.sleep(10) update(a)
其中update函数从数据库拉取信息更新对象a的属性。
尝试编写的测试代码:
def test_while_loop(mocker): with mocker.patch("src.update") as mock_update: mock_update = mocker.MagicMock() mock_update.side_effect = [None, None, None] a.status = mocker.PropertyMock(side_effect = ["status1", "status1", "status2"]) test()
运行时抛出错误:
E TypeError: '!=' not supported between instances of 'PropertyMock' and 'str'
解决方案
错误原因
直接给a.status赋值PropertyMock实例,导致a.status不再是属性值,而是Mock对象本身,和字符串"status2"比较时触发类型错误。正确做法是用patch.object替换对象的属性,而非直接赋值。
修正后的测试代码
def test_while_loop(mocker): # 模拟update函数 with mocker.patch("src.update") as mock_update: # 替换a对象的status属性,用PropertyMock模拟多次返回值 with mocker.patch.object(a, "status", new_callable=mocker.PropertyMock) as mock_status: # 设置status返回序列:前两次返回status1,第三次返回status2 mock_status.side_effect = ["status1", "status1", "status2"] # 执行被测逻辑 test() # 验证update被调用2次(对应循环执行两次) assert mock_update.call_count == 2
关键调整说明
- 使用
mocker.patch.object(a, "status", new_callable=mocker.PropertyMock)替换a的status属性,确保每次访问a.status时获取的是Mock的返回值,而非Mock对象本身。 - 移除多余的
mock_update = mocker.MagicMock(),with mocker.patch(...) as mock_update已生成Mock对象,默认返回None,与原逻辑一致,无需额外设置side_effect。 - 添加断言验证
update调用次数,确保循环按预期执行两次。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

