Django's self.client.login(...) does not work in unit tests Django's self.client.login(...) does not work in unit tests django django

Django's self.client.login(...) does not work in unit tests


The code that doesn't work:

from django.contrib.auth.models import Userfrom django.test import Clientuser = User.objects.create(username='testuser', password='12345')c = Client()logged_in = c.login(username='testuser', password='12345')

Why doesn't it work?

In the snippet above, when the User is created the actual password hash is set to be 12345. When the client calls the login method, the value of the password argument, 12345, is passed through the hash function, resulting in something like

hash('12345') = 'adkfh5lkad438....'

This is then compared to the hash stored in the database, and the client is denied access because 'adkfh5lkad438....' != '12345'

The Solution

The proper thing to do is call the set_password function, which passes the given string through the hash function and stores the result in User.password.

In addition, after calling set_password we must save the updated User object to the database:

user = User.objects.create(username='testuser')user.set_password('12345')user.save()c = Client()logged_in = c.login(username='testuser', password='12345')


An easier way is to use force_login, new in Django 1.9.

force_login(user, backend=None)

For example:

class LoginView(TestCase):    def setUp(self):        self.client.force_login(User.objects.get_or_create(username='testuser')[0])


Can you check like below,

from django.test import TransactionTestCase, Clientclass UserHistoryTest(TransactionTestCase):    self.user = User.objects.create(username='admin', password='pass@123', email='admin@admin.com')    self.client = Client() # May be you have missed this line    def test_history(self):        self.client.login(username=self.user.username, password='pass@123')        # get_history function having login_required decorator        response = self.client.post(reverse('get_history'), {'user_id': self.user.id})        self.assertEqual(response.status_code, 200)

This test case worked for me.