为何Pytest在SQLAlchemy提交后丢失内存对象?调试可过正常运行失败
问题描述
编写测试用例验证从数据库获取对象的函数,断言取回的对象与此前写入数据库的本地创建对象相等,但测试正常运行时始终失败,仅在调试模式下保持变量面板打开查看类属性时才能通过。
测试代码如下:
def test_get_dupe_check_and_rules(engine): test_lead = Lead(id='test_lead') test_dupe_rule = DupeRule(hours=24, found_count=1, dupe_limit='1', result='failed') test_dupe_check = DupeCheck(lead=test_lead, result='failed') test_dupe_check.dupe_rules.append(test_dupe_rule) with Session(engine) as db_session: db_session.add(test_lead) db_session.add(test_dupe_check) db_session.commit() check = get_dupe_check_and_rules(test_lead, engine) assert check == test_dupe_check
现象:执行db_session.commit()后,若未打开变量面板,本地创建对象的属性会被替换为懒加载错误信息:Parent instance <DupeCheck at 0x101c889c0> is not bound to a Session; lazy load operation of attribute 'lead' cannot proceed,原本仅插入数据库未查询的test_dupe_check变为空DupeCheck实例,导致断言失败。
原因分析
- Session关闭后对象脱管:
with代码块结束后,db_session会自动关闭,此前绑定到该Session的test_lead、test_dupe_check等对象会进入脱管状态,不再和任何数据库会话关联。 - 懒加载触发时机差异:
- 调试时打开变量面板,会主动触发对象所有属性的读取(比如展示
test_dupe_check.lead、test_dupe_check.dupe_rules),此时Session尚未关闭,懒加载会正常执行,把关联属性加载到本地对象中,对象保持完整状态。 - 正常运行时,
with块结束Session关闭后,代码后续访问脱管对象的懒加载属性(比如断言相等时对比关联属性),会触发懒加载失败——因为没有Session支持数据库查询,导致属性无法正常读取,甚至对象状态异常。
- 调试时打开变量面板,会主动触发对象所有属性的读取(比如展示
- 对象相等性对比的问题:SQLAlchemy对象的相等性默认会对比所有属性(或依赖Session状态),脱管对象因懒加载失败导致属性缺失或报错,无法和从新Session中查询出来的
check对象匹配,最终断言失败。
内容的提问来源于stack exchange,提问作者doublea
相关产品推荐
相关产品推荐

