3

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 from django.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',
    }
}
Ramon K.
  • 3,402
  • 3
  • 20
  • 29
  • Can you share a project that reproduces this issue on GitHub? *Preferably not your actual project but a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example).* – aaron Dec 01 '22 at 14:25
  • Sure, I guess I'll need to do it anyway. I'll take sometime because there's a big framework behind the tests and trim it will not be trivial. – Ramon K. Dec 01 '22 at 14:30
  • Sounds like this issue: https://stackoverflow.com/questions/14589634/how-to-reset-the-sequence-for-ids-on-postgresql-tables – gregory Dec 06 '22 at 02:26

1 Answers1

0

Maybe you can use TestCase so the DB is created and use the setUp and tearDown to create the Dummy model like this:

class LocalizedModelsTests(TestCase):
    def setUp(self):
        # Create the dummy model
        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(DummyClass)
        # Create any objects you need for your tests here
        DummyClass.objects.create(name='Test')

    def test_dummy_class(self):
        # Test the DummyClass model here

    def tearDown(self):
        DummyClass.objects.all().delete()
        # Delete the dummy model
        with connection.schema_editor() as schema_editor:
            schema_editor.delete_model(DummyClass)

Let me know if this help you.

PDA
  • 26
  • 1