django-currentuser: tearDown problems in unit tests?

I have the following model:

class Business(models.Model):
    ... 
    created_on = models.DateTimeField(auto_now_add=True, editable=False)
    created_by = CurrentUserField(null=True, blank=True, editable=False,       # Attention 4
                                  on_delete=models.SET_NULL)

And I am testing this in the following test case:

class Base(TestCase):
    def setUp(self):
        self.padmin = User.objects.create_user('padmin')
        for u in (self.padmin,):
            u.set_password('password')
            u.save()

        self.business = Business.objects.create(name='name', address='address',
                                                phone_number='123-456-7890')
        self.business2 = Business.objects.create(name='name2', address='address',
                                                 phone_number='123-456-7891')

    def STEP_create_instance(self):
        self.client.login(username='padmin', password='password')
        url = '/'
        self.client.post(url, {})    # Attention: 1


class SafesiteProductionFlowIntegrationTest(Base):

    def test_one(self):
        self.STEP_create_instance()    # Attention: 2

    def test_two(self):
        self.STEP_create_instance()    # Attention: 3 

When I run this test, I am getting the following error:

System check identified no issues (0 silenced).
..E
======================================================================
ERROR: test_before_split2 (instances.tests.test_viewflow.SafesiteProductionFlowIntegrationTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
    return self.cursor.execute(sql)
psycopg2.IntegrityError: insert or update on table "businesses_business" violates foreign key constraint "businesses_business_created_by_id_25175862_fk_auth_user_id"
DETAIL:  Key (created_by_id)=(1) is not present in table "auth_user".


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/test/testcases.py", line 209, in __call__
    self._post_teardown()
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/test/testcases.py", line 893, in _post_teardown
    self._fixture_teardown()
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/test/testcases.py", line 1041, in _fixture_teardown
    connections[db_name].check_constraints()
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/postgresql/base.py", line 235, in check_constraints
    self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/vng/.virtualenvs/prometheus/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
    return self.cursor.execute(sql)
django.db.utils.IntegrityError: insert or update on table "businesses_business" violates foreign key constraint "businesses_business_created_by_id_25175862_fk_auth_user_id"
DETAIL:  Key (created_by_id)=(1) is not present in table "auth_user".


----------------------------------------------------------------------
Ran 2 tests in 0.438s

FAILED (errors=1)

Commenting out the following removes the error:

  • Removing the CurrentUserField in Attention: 4
  • Removing the client post in Attention: 1
  • Removing either of the test (Attention 2 and Attention 3) methods making this test test a single method

It seems like CurrentUserField is causing some issues during tearDown.

Any ideas?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (4 by maintainers)

Most upvoted comments

I run across this problem and spend over 2 days to figure what is breaking our tests (which was quite not obvious since we’ve got two databases setup and we thought that it was causing problems with integrity).

I think that absolute minimum is to mention this issue in the readme and maybe provide at least TestCase subclass/mixin that clears currect_user.

I don’t even know why this issue is closed since no real solution was provided, only a workaround.

I ran into this same problem and resolved it by adding the following to conftest.py (I’m using pytest and pytest-django). This way I don’t have to worry about calling _set_current_user(None) in a tearDown() on every test - the plugin does it for me.

from django_currentuser.middleware import _set_current_user


class UnsetCurrentUserPlugin:
    def pytest_runtest_teardown(self, item):
        _set_current_user(None)
        return


def pytest_configure(config):
    config.pluginmanager.register(UnsetCurrentUserPlugin(), "unset_user_plugin")  # noqa

so it turns out all I need is to have

def tearDown(self):
        _set_current_user(None)

and this problem is fixed.

Is this expected behavior? If so, please include it in the doc so others won’t face the same issue as me.

I encountered this problem today and had some trouble finding out what to do, esp. since each individual test passed, even individual test suites all passed, the failure only occurred when running all tests at once.

In the end I did an explicit _ set_current_user_() in all test classes, i.e. in their setUp function.

I agree with @jakubste that it might be a good idea to mention this in the readme, but I don’t have time ATM to send a PR.

I wasn’t sure how to use @benjhastings code (eg how does django know to call pytest_configure?) but I used this:

We have a “BaseTestClass” that we use everywhere, so I added this as a mixin to that base class:

class ThreadLocalTestHelperMixin:
    """ This fixes a bug (or shortcoming) in django-currentuser

    https://github.com/PaesslerAG/django-currentuser/issues/14
    """
    def tearDown(self):
        _set_current_user(None)

hi @vincentwhales the problem seems to be that the user you create gets deleted at some point before the teardown thus causing the error not present in table “auth_user”. (could be django’s transactional TestCase) Since you create the User in setup I would for once try to move the creation of the user inside test_before_split2

Hope that helps.