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

后端 未结 6 943
栀梦
栀梦 2020-12-02 09:50

I have created users for my unit tests in two ways:

1) Create a fixture for \"auth.user\" that looks roughly like this:

    { 
        \"pk\": 1, 
         


        
相关标签:
6条回答
  • 2020-12-02 10:08

    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='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.

    0 讨论(0)
  • 2020-12-02 10:11

    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')
    
    0 讨论(0)
  • 2020-12-02 10:25

    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])
    
    0 讨论(0)
  • 2020-12-02 10:27

    Check that django.contrib.sessions is added to INSTALLED_APPS because client.login() checks that it is and will always return false if it is not:

    https://docs.djangoproject.com/es/1.9/topics/http/sessions/#enabling-sessions

    0 讨论(0)
  • 2020-12-02 10:27
    from django.test import TestCase
    from django.contrib.auth.models import User
    from django.test import Client
    class MyProfile(TestCase):
        @classmethod
        def setUpClass(self):
            self.username = 'dummy' + data + '@gmail.com'
            self.password = 'Dummy@123'
            user = User.objects.create(username=self.username)
            user.set_password(self.password)
            user.save()
            c = Client()
            self.client_object = c.login(username=self.username, password=self.password)
            self.content_type = "application/json"
            response = self.client_object.post('/api/my-profile/', content_type=self.content_type)
    
    0 讨论(0)
  • 2020-12-02 10:27

    If anyone still following this , I think the attributes 'is_staff' and 'is_active' should be kept True for successfully logging in......

    self.user = User.objects.create(username='testuser',password='pwd',is_active=1,is_staff=1)

    0 讨论(0)
提交回复
热议问题