Reputation: 4911
I was writing some tests involving ZODB and I got stuck for a long time because of the error I was getting in some unit test. Let's call it Test_B
:
Failure/Error: 'NoneType' object has no attribute 'sortKey'
...
File <<< my code somewhere >>>
transaction.commit()
File "/usr/local/lib/python2.7/site-packages/transaction/_manager.py", line 111, in commit
return self.get().commit()
File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 280, in commit
reraise(t, v, tb)
File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 271, in commit
self._commitResources()
File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 386, in _commitResources
L.sort(key=rm_key)
File "/usr/local/lib/python2.7/site-packages/transaction/_transaction.py", line 555, in rm_key
return func()
File "/usr/local/lib/python2.7/site-packages/ZODB/Connection.py", line 813, in sortKey
return "%s:%s" % (self._storage.sortKey(), id(self))
Thankfully I found out eventually that I forgot to call a transaction.commit()
in a test that runs before Test_B
called (unsurprisingly) Test_A
. The sequence of events as recorded by the log looks thus:
<<< Test_A begins >>>
23:01:41 DEBUG txn.140735119446400: new transaction
...
<<< no further mentions of txn.140735119446400 being committed or aborted >>>
<<< Test_A ends >>>
<<< Test_B begins >>>
23:01:41 DEBUG txn.140735119446400: new transaction
23:01:41 DEBUG my_spec: *** MANUALLY altered DB in Test_B body
...
<<< Test_B bails out due to error >>>
Note that Test A
succeeds: this is wrong! I want Test A
to fail and tell me I have outstanding changes in a transaction that I had forgotten to commit.
How can I do this with ZODB? I can't find anything in the documentation that I could use to find out whether I'm in a transaction with changes or not.
Obviously, with that check, then I can stick it into the AfterEach
block of all my unit tests in the suite.
Upvotes: 2
Views: 958
Reputation: 1123400
You'd normally close the connection to the ZODB between tests, to make sure the tests are isolated.
Closing a ZODB connection with an active transaction will raise an exception:
>>> from ZODB.FileStorage import FileStorage
>>> from ZODB.DB import DB
>>> storage = FileStorage('Data.fs')
>>> db = DB(storage)
>>> connection = db.open()
>>> root = connection.root()
>>> root['foo'] = 'bar'
>>> connection.close()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/ZODB/Connection.py", line 286, in close
raise ConnectionStateError("Cannot close a connection joined to "
ZODB.POSException.ConnectionStateError: Cannot close a connection joined to a transaction
Upvotes: 1