web-dev-qa-db-fra.com

Le self.client.login (...) de Django ne fonctionne pas dans les tests unitaires

J'ai créé des utilisateurs pour mes tests unitaires de deux manières:

1) Créez un appareil pour "auth.user" qui ressemble à peu près à ceci:

    { 
        "pk": 1, 
        "model": "auth.user", 
        "fields": { 
            "username": "homer", 
            "is_active": 1, 
            "password": 
"sha1$72cd3$4935449e2cd7efb8b3723fb9958fe3bb100a30f2", 
            ... 
        } 
    }

J'ai laissé de côté les parties apparemment sans importance.

2) Utilisez 'create_user' dans la fonction setUp (bien que je préfère tout garder dans ma classe d'appareils):

def setUp(self): 
       User.objects.create_user('homer', '[email protected]', 'simpson') 

Notez que le mot de passe est simpson dans les deux cas.

J'ai vérifié que ces informations sont correctement chargées à maintes reprises dans la base de données de test. Je peux saisir l'objet User à l'aide de User.objects.get. Je peux vérifier que le mot de passe est correct en utilisant "check_password". L'utilisateur est actif.

Pourtant, invariablement, self.client.login (username = 'homer', password = 'simpson') FAILS. Je ne comprends pas pourquoi. Je pense avoir lu toutes les discussions sur Internet à ce sujet. Quelqu'un peut-il aider?

Le code de connexion dans mon test unitaire ressemble à ceci:

    login = self.client.login(username='homer', password='simpson') 
    self.assertTrue(login) 

Merci.

66
thebossman

Le code qui ne fonctionne pas:

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')

Pourquoi ça ne marche pas?

Dans l'extrait ci-dessus, lorsque le User est créé, le hachage de mot de passe réel est défini sur 12345. Lorsque le client appelle la méthode login, la valeur de l'argument password, 12345, est passé par la fonction de hachage, résultant en quelque chose comme

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

Il est ensuite comparé au hachage stocké dans la base de données et l'accès au client est refusé car 'adkfh5lkad438....' != '12345'

La solution

La bonne chose à faire est d'appeler le set_password, qui transmet la chaîne donnée par la fonction de hachage et stocke le résultat dans User.password.

De plus, après avoir appelé set_password nous devons enregistrer l'objet User mis à jour dans la base de données:

user = User.objects.create(username='testuser')
user.set_password('12345')
user.save()

c = Client()
logged_in = c.login(username='testuser', password='12345')
93
Pedro M Duarte

Un moyen plus simple consiste à utiliser force_login , nouveau dans Django 1.9.

force_login(user, backend=None)

Par exemple:

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

Vérifiez que Django.contrib.sessions Est ajouté à INSTALLED_APPS Car client.login() vérifie qu'il est et retournera toujours faux s'il ne l'est pas:

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

5
e-satis

Pouvez-vous vérifier comme ci-dessous,

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)

Ce cas de test a fonctionné pour moi.

4
Muthuvel
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
aravind allu