Django's self.client.login(...) does not work in unit tests
The code that doesn't work:
from django.contrib.auth.models import User
from django.test import Client
user = 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, Client
class UserHistoryTest(TransactionTestCase):
self.user = User.objects.create(username='admin', password='pass@123', email='[email protected]')
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.