Django’s TestCase class wraps each test in a transaction and rolls back that transaction after each test, in order to provide test isolation.
Apparently, however, only operations in the default
database are within the scope of the transaction. I have a multiple database setup with a router that directs ORM calls on some models to a second database. This means that in the following example, test2
fails:
class MyTestCase(TestCase):
def test1(self):
# Let's say Foo model ORM calls are routed to a different DB
foo = Foo.objects.create(...)
assert foo.is_ok()
def test2(self):
assert not Foo.objects.exists()
The most immediate solution to this problem would be to override the tearDown
method in MyTestCase
and manually make sure to delete all Foo
objects. But this is a bit annoying because it's sort of a hack and database sequences (e.g. autoincrement columns) won't be reset for example, only after the test suite is done and the database is destroyed.
Is there a way to properly fix this, making sure all database operations are by default made inside a transaction and rolled back at the end of each test?
[UPDATE]
Here's my router:
class FooRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'foo':
return 'foo_db'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'foo':
return 'foo_db'
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'foo':
return db == 'foo_db'
return None
As multi_db is deprecated, you can now achieve test with multiple database with the new attribute databases
class YourTestCase(TestCase):
databases = '__all__'
def test_something(self):
pass
In case you are not using DB Router, you can try to add multi_db = True
to TestCase to call flush for all databases
class YourTestCase(TestCase):
multi_db = True
def test_something(self):
pass
Django docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With