When I run my tests with the DB empty (the actual application DB), everything goes fine. But when the DB has data, Django raises an IntegrityError
for basically every test. The stact trace looks like the following (but for every test):
======================================================================
ERROR: test_api_get_detail (core.projects.tests.test_project_api.ProjectConfidentialPrivateAPITests)
Getting confidential object via API (GET)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/ramonkcom/Desktop/management/management-backend/venv/lib/python3.10/site-packages/django/test/testcases.py", line 299, in _setup_and_call
self._post_teardown()
File "/Users/ramonkcom/Desktop/management/management-backend/venv/lib/python3.10/site-packages/django/test/testcases.py", line 1199, in _post_teardown
self._fixture_teardown()
File "/Users/ramonkcom/Desktop/management/management-backend/venv/lib/python3.10/site-packages/django/test/testcases.py", line 1461, in _fixture_teardown
connections[db_name].check_constraints()
File "/Users/ramonkcom/Desktop/management/management-backend/venv/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 383, in check_constraints
raise IntegrityError(
django.db.utils.IntegrityError: The row in table 'custom_fields_customfield' with primary key '1' has an invalid foreign key: custom_fields_customfield.definition_id contains a value '1' that does not have a corresponding value in custom_fields_customfielddefinition.id.
At first I thought this was a problem with my fixtures. But they work just fine to set up the application basic data. The DB seems to be the key issue: if it has data, the tests crash, if it's empty, the tests work.
The most weird part is that the error being raised doesn't match with reality, and by that I mean: the CustomFieldDefinition
object with pk=1 exists in the DB. Anyway, it shouldn't matter, since I expect Django to build an in-memory DB for every test. It's just an additional piece of info for the mistery.
What could be making Django check for the actual DB instead of doing all its thing in-memory?
Additional pieces of info:
I'll work to provide some code example (didn't provide it right from the start because there's a big test framework behind it, and I'll have to trim it). But for now, I'be adding infos and things that I get asked and things I suspect might be causing the issue:
I'm on Python 3.10.8 and Django 4.0.5
Most of the test cases are inheriting from
django.test.TestCase
, but some are inheriting fromdjango.test.TransactionTestCase
.I'm using
TransactionTestCase
in some cases because I need to create dummy models (and maybe this implementation is part of the problem somehow). Example:
# THE DUMMY CLASS
@localized
class DummyClass(models.Model):
"""Represents a dummy model for testing purpose"""
class Meta:
app_label = 'apps.localizer'
name = models.CharField(max_length=255, blank=True, null=True)
# THE TEST CASE SETUP/TEARDOWN
class LocalizedModelsTests(TransactionTestCase):
def setUp(self):
with connection.schema_editor() as schema_editor:
schema_editor.create_model(DummyClass)
def tearDown(self):
with connection.schema_editor() as schema_editor:
schema_editor.delete_model(DummyClass)
- The database settings on
settings.py
(still on dev, so there's no other setting that could replace this one):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}