问题
更新@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 的 testrunner,但我可以确认无论我使用哪个 testrunner,都会发生此问题。
另外,我发现了几个以前的问题,但建议的解决方案要么是特定于旧版本的 Django,要么在这种情况下没有帮助(例如,请参见此处)。
解决方案(结合两个好的答案)
对于这个问题,我收到了两个非常好的答案,这两个都突出了我发布的片段中的重要疏忽。该问题与@login_required
' 的行为无关,与 (a) 错误地签署用户和 (b) 检查用户身份验证错误有关。
我很难选择接受哪个答案,但经过一番思考,我决定接受 Konrad Hałas 的答案,因为它指出了我的关键疏忽,这是意外行为的根源。
尽管如此,如果我没有使用有故障的测试线,我会更快地发现这一点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())