更新:事实证明,这个问题与@login_required
装饰器没什么关系!
当我尝试测试用@login_required
修饰的视图时,我会遇到挑剔的行为。
我有一个实际上可以转到用@login_required
修饰的视图的测试(密码更改视图)。但是,不同的测试总是被重定向到登录。无论我尝试重写它的哪种方式,它都不会让我的测试用户通过,即使我正在记录用户并事先断言user.is_authenticated()
。
以下是有问题的相关测试片段:
# Log user in
self.client.login(username=user.username, password=user.password)
self.assertTrue(user.is_authenticated())
# Go to account_edit view
url = reverse('account_edit')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'users/account_edit_form.html')
这不可避免地会重定向到登录视图,就好像用户没有登录一样。
我可以确认此行为未反映在应用的“正常”功能中;当我实际运行服务器然后导航到此视图时,装饰器完全按预期工作(即,它允许登录时访问,并重定向到登录视图)。
使用Django 1.3.1。我正在使用django-nose的测试人员,但我可以确认无论我使用哪个测试人员都会发生这个问题。
此外,我发现了之前的几个问题,但建议的解决方案要么特别适用于旧版本的Django,要么在这种情况下没有帮助(例如,请参阅here)。
我收到了两个非常好的答案,这两个问题突出了我发布的片段中的重要疏忽。该问题与@login_required
的行为无关,而且与(a)错误地签署用户以及(b)检查用户身份验证错误有关。
我很难选择接受哪个答案,但经过一番思考后,我决定接受KonradHałas的答案,因为它确定了我的关键疏忽,这是意外行为的根源。 / p>
尽管如此,如果我没有使用错误的测试线self.assertTrue(user.is_authenticated())
,我会更快地想出来。因此,要强调解决方案实际上是两个部分,这里是修复有问题代码的两个步骤:
# Log user in *NOTE: Password needs to be raw (from Konrad's answer)
self.client.login(username=user.username, password="pass")
self.assertTrue(user.is_authenticated()) # <-- still not correct
断言行仍然有问题,因为有效用户始终满足user.is_authenticated()
。有关此问题的解释,请参阅Alasdair的信息。因此,修复此代码的第二步是:
# Log user in *NOTE: Password needs to be raw (from Konrad's answer)
login_successful = self.client.login(username=user.username, password="pass")
self.assertTrue(login_successful) # Much better! (see Alasdair's answer)
最后,如果你需要测试你的用户是否使用client.login
登录(即测试登录表单),这应该有效:
self.assertTrue(response.context['user'].is_authenticated())
答案 0 :(得分:8)
user.password
是密码哈希。您无法使用它登录。您需要使用原始密码:
self.client.login(username=user.username, password='<user password>')
答案 1 :(得分:3)
这里的问题是,is_authenticated
方法总是为True
实例返回User
。
在模板或视图中,它可能很有用 - 如果request.user.is_authenticated()
为True
,那么您拥有真实用户,而不是AnonymousUser
,并且可以相应地进行操作。但是,如果您开始使用User
对象,那么is_authenticated()
可能会让您感到困惑!
您可以检查测试客户端的login()
方法的返回值,以测试它是否成功。
login_successful = c.login(username='fred', password='secret')
self.assertTrue(login_successful)