test - pruebas unitarias django
El archivo self.client.login de Django(...) no funciona en pruebas unitarias (5)
El código que no funciona:
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'')
¿Por qué no funciona?
En el fragmento anterior, cuando se crea el usuario, el hash de contraseña real se establece en 12345
. Cuando el cliente llama al método de login
, el valor del argumento de la password
, 12345
, se pasa a través de la función hash, lo que da como resultado algo así como
hash(''12345'') = ''adkfh5lkad438....''
Esto se compara con el hash almacenado en la base de datos, y al cliente se le niega el acceso porque ''adkfh5lkad438....'' != ''12345''
La solución
Lo correcto es llamar a la función set_password
, que pasa la cadena dada a través de la función hash y almacena el resultado en User.password
.
Además, después de llamar a set_password
, debemos guardar el objeto User
actualizado en la base de datos:
user = User.objects.create(username=''testuser'')
user.set_password(''12345'')
user.save()
c = Client()
logged_in = c.login(username=''testuser'', password=''12345'')
Creé usuarios para mis pruebas unitarias de dos maneras:
1) Cree un accesorio para "auth.user" que se vea más o menos así:
{
"pk": 1,
"model": "auth.user",
"fields": {
"username": "homer",
"is_active": 1,
"password":
"sha1$72cd3$4935449e2cd7efb8b3723fb9958fe3bb100a30f2",
...
}
}
He omitido las partes aparentemente sin importancia.
2) Use ''create_user'' en la función setUp (aunque prefiero mantener todo en mi clase de accesorios):
def setUp(self):
User.objects.create_user(''homer'', ''[email protected]'', ''simpson'')
Tenga en cuenta que la contraseña es simpson en ambos casos.
Comprobé que esta información se carga correctamente en la base de datos de prueba una y otra vez. Puedo tomar el objeto User usando User.objects.get. Puedo verificar que la contraseña sea correcta usando ''check_password''. El usuario está activo.
Sin embargo, invariablemente, self.client.login (username = ''homer'', password = ''simpson'') FALLA. Estoy desconcertado sobre por qué. Creo que he leído todas las discusiones en Internet relacionadas con esto. ¿Alguien puede ayudar?
El código de inicio de sesión en mi prueba de unidad se ve así:
login = self.client.login(username=''homer'', password=''simpson'')
self.assertTrue(login)
Gracias.
Compruebe que django.contrib.sessions
se haya agregado a INSTALLED_APPS
porque client.login()
comprueba que es y siempre devolverá false si no lo está:
https://docs.djangoproject.com/es/1.9/topics/http/sessions/#enabling-sessions
Puedes verificar como a continuación,
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)
Este caso de prueba funcionó para mí.
Si alguien aún sigue esto, creo que los atributos ''is_staff'' y ''is_active'' deben mantenerse True para iniciar sesión correctamente ......
self.user = User.objects.create(username=''testuser'',password=''pwd'',is_active=1,is_staff=1)
Una forma más fácil es usar force_login
, nuevo en Django 1.9.
force_login(user, backend=None)
Por ejemplo:
class LoginView(TestCase):
def setUp(self):
self.client.force_login(User.objects.get_or_create(username=''testuser'')[0])