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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:22:42