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

the*_*man 69 django unit-testing django-authentication django-testing

我已经通过两种方式为我的单元测试创​​建了用户:

1)为"auth.user"创建一个看起来大致如下的夹具:

    { 
        "pk": 1, 
        "model": "auth.user", 
        "fields": { 
            "username": "homer", 
            "is_active": 1, 
            "password": 
"sha1$72cd3$4935449e2cd7efb8b3723fb9958fe3bb100a30f2", 
            ... 
        } 
    }
Run Code Online (Sandbox Code Playgroud)

我遗漏了看似不重要的部分.

2)在setUp函数中使用'create_user'(尽管我宁愿将所有内容保存在我的fixtures类中):

def setUp(self): 
       User.objects.create_user('homer', 'ho...@simpson.net', 'simpson') 
Run Code Online (Sandbox Code Playgroud)

请注意,在这两种情况下密码都是simpson.

我已经验证了这个信息一次又一次正确地加载到测试数据库中.我可以使用User.objects.get获取User对象.我可以使用'check_password'验证密码是否正确.用户处于活动状态.

然而,self.client.login(username ='homer',password ='simpson')FAILS总是如此.我很困惑为什么.我想我已经阅读了与此相关的每一个互联网讨论.有人可以帮忙吗?

单元测试中的登录代码如下所示:

    login = self.client.login(username='homer', password='simpson') 
    self.assertTrue(login) 
Run Code Online (Sandbox Code Playgroud)

谢谢.

Ped*_*rte 98

代码不起作用:

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')
Run Code Online (Sandbox Code Playgroud)

为什么不起作用?

在上面的代码段中,User创建时,实际密码哈希设置为12345.当客户端调用该login方法时,password参数的值12345将通过哈希函数传递,从而产生类似的结果

hash('12345') = 'adkfh5lkad438....'
Run Code Online (Sandbox Code Playgroud)

然后将其与存储在数据库中的哈希进行比较,并拒绝客户端访问,因为 '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')
Run Code Online (Sandbox Code Playgroud)

  • 你使用`User.objects.create_superuser()`和`User.objects.create_user()`来执行这个`set_password()`调用. (34认同)

Wei*_*gTu 42

一种更简单的方法是force_login在Django 1.9中使用new.

force_login(user, backend=None)
Run Code Online (Sandbox Code Playgroud)

例如:

class LoginView(TestCase):
    def setUp(self):
        self.client.force_login(User.objects.get_or_create(username='testuser')[0])
Run Code Online (Sandbox Code Playgroud)


Mut*_*vel 5

你能像下面这样检查吗?

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)
Run Code Online (Sandbox Code Playgroud)

这个测试用例对我有用。


e-s*_*tis 5

检查是否django.contrib.sessions已添加,INSTALLED_APPS因为client.login()检查它是否存在,如果不是,则始终返回false:

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

  • +1为此.即使在中间件类中使用`django.contrib.sessions.middleware.SessionMiddleware`,您仍然无法通过django.test.Client登录.我花了一个星期才找到这个答案 (2认同)