Django tests not flushing the database

Hello! This is Django 4.1.2 and I am testing my authentication with the django.test.Client and two tests cases fail because once I run my test_login_success test case once, the user remains authenticated forever, even when I am instantiating a new client in the class setUp and even deleting the user in the tearDown.

My code:

    from django.test import Client, TestCase
    
    from app.users.models import User
    
    
    class TestLogin(TestCase):
    
        def setUp(self):
            super().setUp()
            self.email = 'test@test.com'
            self.password = 'SomeRandomPass96'
            User.objects.create_user(email=self.email, password=self.password)
            self.client = Client()
    
        def tearDown(self):
            User.objects.filter(email=self.email).delete()
            super().tearDown()
    
        def test_not_authenticated(self):  # success the first time, fails (by assertionError) after test_login_success is executed for the first time.
            user = User.objects.get(email=self.email)
            assert not user.is_authenticated
    
        def test_login_success(self):  # always success
            self.client.post(
                '/users/login/',
                {'email': self.email, 'password': self.password}
            )
        
            user = User.objects.get(email=self.email)
            assert user.is_authenticated
    
        def test_login_wrong_credentials(self):  # success the first time, fails (by assertionError) after test_login_success is executed for the first time.
            self.client.post(
                '/users/login/',
                {'email': self.email, 'password': 'wrongPassword123'}
            )
    
            user = User.objects.get(email=self.email)
            assert not user.is_authenticated

I’ve put a breakpoint() in the setUp and realized that the user is authenticated as soon as it is created. It’s weird since I am using a custom User model but the Auth Backend is the Django’s default. By the way I am also using the default database configuration (with sqlite) and I am not seeing any “test_…” database when I run the tests as the documentation describes.

My custom User in case it results useful:

from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models

from app.utils.models import AuditedModel


class UserManager(BaseUserManager):

    def create_user(self, email: str, password: str = None):
        u = User(email=email)
        u.set_password(password)
        u.save()

    def create_superuser(self, email: str, password: str = None):
        self.create_user(email, password)


class User(AbstractUser, AuditedModel):

    email = models.EmailField(
        unique=True,
        error_messages={'unique': 'El email se encuentra en uso.'}
    )
    username = None
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self) -> str:
        return self.email

AuditedModel is just an abstract class to audit creation and updates:

class AuditedModel(models.Model):
    """
    Model that adds utility fields such as time created and last time
    modified.
    """

    created = models.DateTimeField(auto_now=True)
    modified = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True
        get_latest_by = 'created'
        ordering = ['-created', '-modified']

Any clue? Thanks in advance!

The is_authenticated attribute does not work like you are thinking it works.

It actually has nothing to do with the status of whether or not a User is logged on.

It’s really only checking whether the User object you have is an instance of User or an instance of AnonymousUser.

See the docs at User.is_authenticated.

1 Like

(post deleted by author)

You’re right! I’ve been doing it wrong, confused with the request.user which is in fact an AnonymousUser if it’s not authenticated as you said. But in the tests I am directly getting a User instance so it’s 100% my bad. Thank you very much

What db are you using? There is a known issue with Postgresql and latest Django running the test cases correctly. Try sqlite and see if you get the same result.