Django的self.client.login(...)在单元测试中不起作用

oxf4rvwz  于 2023-05-19  发布在  Go
关注(0)|答案(8)|浏览(153)

我用两种方法为我的单元测试创建了用户:
1)为“auth.user”创建一个fixture,大致如下所示:

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

我省略了那些看起来不重要的部分。
2)在setUp函数中使用'create_user'(尽管我更愿意将所有内容都保留在fixture类中):

def setUp(self): 
       User.objects.create_user('homer', 'ho...@simpson.net', 'simpson')

请注意,这两种情况下的密码都是simpson。
我已经一次又一次地验证了这些信息被正确地加载到测试数据库中。我可以使用User.objects.get获取User对象。我可以使用“check_password”验证密码是否正确。用户处于活动状态。
但是,self.client.login(username ='homer',password ='simpson')总是失败。我不知道为什么。我想我已经阅读了所有关于这个的网上讨论。有人能帮忙吗?
我的单元测试中的登录代码如下所示:

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

谢谢。

3bygqnnd

3bygqnnd1#

不工作的代码:

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

为什么不行?

在上面的代码片段中,当创建“User”时,实际的密码哈希被设置为“12345”。当客户端调用login方法时,password参数的值12345将通过哈希函数传递,结果类似于

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

然后将其与存储在数据库中的散列进行比较,客户端被拒绝访问,因为'adkfh5lkad438....' != '12345'

解决方案

正确的做法是调用set_password函数,该函数将给定的字符串传递给哈希函数,并将结果存储在User.password中。
此外,在调用set_password之后,我们必须将更新后的User对象保存到数据库中:

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

c = Client()
logged_in = c.login(username='testuser', password='12345')

或者,使用更专业的接口

# this encodes the password and calls save()
user = User.objects.create_user(username='testuser', password='12345')

c = Client()
logged_in = c.login(username='testuser', password='12345')

如果你想要一个超级用户,使用create_superuser

qnyhuwrf

qnyhuwrf2#

一个更简单的方法是使用force_login,Django 1.9中的新功能。

force_login(user, backend=None)

例如:

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

w9apscun3#

检查django.contrib.sessions是否被添加到INSTALLED_APPS中,因为client.login()会检查它是否被添加,如果不是,则总是返回false:
https://docs.djangoproject.com/es/1.9/topics/http/sessions/#enabling-sessions

l5tcr1uw

l5tcr1uw4#

你能像下面这样检查一下吗

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)

这个测试案例对我很有效。

k5hmc34c

k5hmc34c5#

如果使用rest_framework,请确保启用了基于会话的身份验证。那是我的问题
转到您的settings.py文件并检查REST_FRAMEWORK -> DEFAULT_AUTHENTICATION_CLASSES是否包含SessionAuthentication

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.TokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
    ...
}

看起来login方法使用了vanilla Django基于会话的方法,所以如果你只使用rest_framework的token auth,那将会失败。

xmq68pz9

xmq68pz96#

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

n9vozmp47#

如果你在测试用例时只需要一个经过身份验证的用户,你可以使用force_login,它不需要任何身份验证属性,只需要传递用户对象。

def test_something_view(self):
        client = Client()
        client.force_login(self.user)
        response = client.post(reverse('your custom url'), follow=True)
        self.assertEqual(response.status_code, 200)
dxxyhpgq

dxxyhpgq8#

如果任何人仍然遵循这一点,我认为属性'is_staff'和'is_active'应该保持为True以成功登录......
self.user = User.objects.create(username='testuser',password='pwd',is_active=1,is_staff=1)

相关问题