My code:
- Django 4.1
- I am using multiple postgresql schemas for my models, postgresql12 with out-of-box ubuntu 20.04 setup.
- I am performing unit tests of some code which uses transactions.
- migrations are created
- When running other non-transaction tests with django
TestCase
, everything works normal. - When running transaction test with
TransactionTestCase
(even with empty test function), this happens:
django.db.utils.NotSupportedError: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "users_user_permissions" references "auth_permission".
HINT: Truncate table "users_user_permissions" at the same time, or use TRUNCATE ... CASCADE.
...
django.core.management.base.CommandError: Database test_mike3 couldn't be flushed. Possible reasons:
* The database isn't running or isn't configured correctly.
* At least one of the expected database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin sqlflush'. That's the SQL this command wasn't able to run.
django-admin sqlflush:
BEGIN;
TRUNCATE "django_content_type", "auth_group_permissions", "django_session", "auth_group", "auth_permission", "django_admin_log" RESTART IDENTITY;
COMMIT;
My solution
I have gone into code and added _fixture_teardown(self)
override to my ExampleTestCase(TransactionTestCase)
: basically changed allow_cascade=True
in flush command.
Since by this documentation: https://docs.djangoproject.com/en/4.1/topics/testing/advanced/ not setting available_apps
might cause memory leaks, I will probably set all my apps to it so allow_cascade
is set to True automatically. Original django code:
def _fixture_teardown(self):
# Allow TRUNCATE ... CASCADE and don't emit the post_migrate signal
# when flushing only a subset of the apps
for db_name in self._databases_names(include_mirrors=False):
# Flush the database
inhibit_post_migrate = (
self.available_apps is not None or
( # Inhibit the post_migrate signal when using serialized
# rollback to avoid trying to recreate the serialized data.
self.serialized_rollback and
hasattr(connections[db_name], '_test_serialized_contents')
)
)
call_command('flush', verbosity=0, interactive=False,
database=db_name, reset_sequences=False,
allow_cascade=self.available_apps is not None,
inhibit_post_migrate=inhibit_post_migrate)
Do you have any idea why is it unable to flush db with TransactionTestCase in the first place?