我目前正在为我的应用程序编写单元测试,并且我有一个常见的错误,即函数想要在会话已经关闭后访问数据库对象。为了确保应用程序中不存在此错误,我想故意触发它。如果我拥有它,我会修复错误,并确保它消失了。
然而,我似乎很难做到这一点:
DBSession = scoped_session(
sessionmaker(
extension=ZopeTransactionExtension(),
))
db_session = DBSession()
obj = Object()
db_session.add(obj)
obj.property = "a"
db_session.expire_on_commit = True
db_session.expire(obj)
db_session.expunge(obj)
transaction.commit()
db_session.close()
assert obj.property == "a"
这是一个简短的例子。我希望transaction.commit
或db_session.close()
触发重复,但上面的组合代码(从谷歌搜索,似乎是所有错误的组合)都可以触发此异常。
真正的错误来自于:我有一个数据库存储会话,一旦我想在cookie中设置会话ID,会话就说它是分离的。所以我只是在本地缓存它,它不像我在它创建后会改变它。
最后,当试图将其故意过期时:
assert obj in db_session
db_session.expire(obj)
我得到一个例外:InvalidRequestError: Instance ... is not persistent within this Session
。这让我完全困惑...在这里谷歌搜索没有透露任何有用的东西。有什么想法吗?
修改:感谢zzzeek的评论,我也测试过:
assert db_session is \
orm.session.Session.object_session(obj)
assert isinstance(obj, Object)
assert isinstance(Object.property, orm.attributes.InstrumentedAttribute)
注意:所有代码示例都被缩短并转换,但这些操作以这种方式执行,所有assert
语句都成立。
编辑2 :我必须在上面的代码中修复错误并替换
obj = db_session.query(Object)[0] # Object is from DB, just a short example
通过
obj = Object()
db_session.add(obj)
因为它实际上是新创建的对象而不是查询它。查询工作查找(抱歉!)
编辑3 :在某种程度上我修复了原始问题:我现在可以强制我最初想要的异常。但是,我仍然得到了无法解释的InvalidRequestError
,所以我决定制作一个基本的要点来证明这个问题:https://gist.github.com/Javex/5885669。您可以将其作为独立脚本运行,也可以通过py.test
运行。