如何使用ZopeTransactionExtension激活DetachedInstanceError进行单元测试

时间:2013-06-27 19:46:25

标签: python sqlalchemy pyramid zope pytest

我目前正在为我的应用程序编写单元测试,并且我有一个常见的错误,即函数想要在会话已经关闭后访问数据库对象。为了确保应用程序中不存在此错误,我想故意触发它。如果我拥有它,我会修复错误,并确保它消失了。

然而,我似乎很难做到这一点:

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.commitdb_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运行。

0 个答案:

没有答案