为何Flask删除路由pytest测试无db.session.commit也通过但实际运行失效
问题原因解答
核心是SQLAlchemy的会话特性和测试、生产环境的会话行为差异导致的:
- 同会话内未提交变更可见:SQLAlchemy的会话自带状态缓存,同一会话内执行
db.session.delete()后,哪怕没调用commit(),后续该会话发起的所有查询都会自动感知到待提交的变更:标记为删除的对象会被过滤、级联删除的关联数据变更也能被查询到。测试过程中,路由里的删除操作、重定向后渲染页面的查询、测试用例里写的数据库断言,全部运行在同一个会话下,所以所有断言都符合预期。 - 测试环境会话复用:Flask测试客户端的请求默认在同一个测试线程内执行,不会像生产环境那样为每个独立请求分配独立的会话。你在测试里先后发起的删除请求、重定向后的列表请求,用的是同一个数据库会话,自然能读取到未提交的删除变更。
- 生产环境跨会话不可见:实际运行时,删除请求是一个独立会话,执行完删除逻辑后没有提交,请求结束时会话会自动回滚所有未提交变更;重定向后的列表请求是全新的独立会话,直接查询数据库里的原始数据,自然还能看到被删除的俱乐部。
如果要让测试覆盖到提交逻辑的正确性,可以在删除请求执行后手动销毁当前会话再做断言:
# 在删除请求执行后加这一行 db.session.remove() # 再执行后续的数据库断言,就能复现生产环境的bug c = Club.query.get(1) assert c is None
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

