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

为何session.commit()与session.flush()的assert_not_called未生效?

问题原因及解决办法

你的测试能通过,核心问题是mock的层级没搞对:

  • 你patch的session_scope_retries是个上下文管理器函数,当代码执行with session_scope_retries() as db_session时,真正拿到的db_session是这个上下文管理器__enter__()方法返回的对象。
  • 但你现在直接在被patch的session_scope_retries对象上断言flush和commit是否被调用,而这两个方法其实是调用在__enter__返回的会话实例上,根本不是patch的那个函数对象。所以原来的断言相当于在检查一个完全没被调用过的方法,自然会通过。

修复后的测试代码

def test_bad_currency_data_not_persisted(mock_check_currency, metadata_dict):
    ...
    # 先创建一个模拟的数据库会话对象,包含flush和commit方法
    mock_db_session = Mock()
    with patch('exchanges.exchange.session_scope_retries') as mock_session_scope:
        # 让上下文管理器返回我们创建的模拟会话对象
        mock_session_scope.return_value.__enter__.return_value = mock_db_session
        check_currency(security_files_generated)
        # 对真正被调用的模拟会话对象做断言
        mock_db_session.flush.assert_not_called()
        mock_db_session.commit.assert_not_called()

额外说明

原来的测试里,db_session.flush和db_session.commit其实是在访问被patch的session_scope_retries函数的属性,这个函数本身从来没被调用过这两个方法,所以assert_not_called()肯定会通过。只有正确mock出上下文管理器返回的会话实例,才能准确捕获到flush和commit的调用行为,让测试符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:54:57