Reputation: 5147
I have read this Q&A, and already try to catch exception on my code that raise an IntegrityError exception, this way :
self.assertRaises(IntegrityError, db.session.commit())
But somehow my unit test still failed and stop with IntegrityError exception. I expect it to say OK as I already expect to have exception in my unit test. This was cause by code that tries to insert row having the same unique field values.
Any idea?
Upvotes: 7
Views: 2480
Reputation: 101
I've just spent a few hours trying to understand why my test was failing with IntegrityError
during execution, but failed to catch it with with pytest.raises
block (session builder is simplified, but notice autocommit
flag):
async with async_session_maker(autocommit=True) as session:
with pytest.raises(sqlalchemy.exc.IntegrityError):
sqlachemy.execute(statement_which_violates_foreign_key_contstraint)
Trouble appeared on an order of session block and pytest block. The exception will be raised on session.commit()
statement which is hidden in __aexit__
method of AsyncSession.
Solution - change the order:
with pytest.raises(sqlalchemy.exc.IntegrityError):
async with async_session_maker(autocommit=True) as session:
sqlachemy.execute(statement_which_violates_foreign_key_contstraint)
Upvotes: 0
Reputation: 100756
One of these will to the trick:
# ... only if version >= 2.7
with self.assertRaises(IntegrityError):
db.session.commit()
Or:
self.assertRaises(IntegrityError, db.session.commit)
The difference between your example and the correct way is:
# Your example: You call db.session.commit(), this will raise an exception before
# assertRaises is called
self.assertRaises(IntegrityError, db.session.commit())
# Correct way: Pass what should be called to assertRaises,
# let assertRaises invoke it and check for exception
self.assertRaises(IntegrityError, db.session.commit)
I prefer to use assertRaises as a context manager (using with
).
Upvotes: 6