2011-09-09 26 views
27

我已经开始使用Django的测试框架,并且一切正常,直到我开始测试已认证的页面。在Django测试框架中登录()

为了简单起见,我们说这是一个测试:

class SimpleTest(TestCase): 
    def setUp(self): 
     user = User.objects.create_user('temporary', '[email protected]', 'temporary') 

    def test_secure_page(self): 
     c = Client() 
     print c.login(username='temporary', password='temporary') 
     response = c.get('/users/secure/', follow=True) 
     user = User.objects.get(username='temporary') 
     self.assertEqual(response.context['email'], '[email protected]') 

我运行这个测试后,它失败了,我看到打印登录的返回值()返回,但response.content被重定向到登录页面(如果登录失败,则认证装饰器重定向到登录页面)。我已经把装饰一个破发点,做身份验证:

def authenticate(user): 
    if user.is_authenticated(): 
     return True 
    return False 

,它真的返回。 test_secure_page()中的第4行正确检索用户。

这是视图功能:

@user_passes_test(authenticate, login_url='/users/login') 
def secure(request): 
    user = request.user 
    return render_to_response('secure.html', {'email': user.email}) 

当然,如果我尝试登录,通过应用程序(外测试),一切工作正常。

+1

请发布您正在测试的视图的代码。 –

+0

@ S.Lott我没有测试我的登录页面(尽管我也尝试过,但这也不起作用),但其余部分是系统的“安全”部分。出于这个原因,我尝试使用login()。 – kevin

+1

@kevin。问题是登录帖子会创建一个客户端使用的cookie。没有cookie,没有安全访问。 AFAIK,'login()'函数不会创建cookie并将其返回给客户端。你可以尝试重现Django文档中的例子,看看它们是否适合你? –

回答

25

问题是您没有将RequestContext传递给您的模板。

此外,您可能应该使用login_required修饰器和TestCase类中内置的客户端。

我把它改写这样的:

#views.py 
from django.contrib.auth.decorators import login_required 
from django.shortcuts import render 

@login_required(login_url='/users/login') 
def secure(request): 
    user = request.user 
    return render(request, 'secure.html', {'email': user.email}) 



#tests.py 
class SimpleTest(TestCase): 
    def setUp(self): 
     user = User.objects.create_user('temporary', '[email protected]', 'temporary') 

    def test_secure_page(self): 
     self.client.login(username='temporary', password='temporary') 
     response = self.client.get('/manufacturers/', follow=True) 
     user = User.objects.get(username='temporary') 
     self.assertEqual(response.context['email'], '[email protected]') 
+1

为什么你认为不通过RequestContext应该是一个问题(上下文给render_to_response())?当它从浏览器调用时,它在测试框架之外工作(顺便说一句,我尝试传递RequestContext,但同样的事情发生)。此外,验证发生在输入视图之前。我也从TestCase类中尝试了@login_required和client,但同样的事情发生了。 – kevin

+0

我改变了它的工作:self.assertEqual(response.context ['user']。email,'[email protected]') – cor

10

它往往可以使用自定义身份验证后端测试期间bypassess任何一种认证的有用:

from django.contrib.auth.models import User 

class TestcaseUserBackend(object): 
    def authenticate(self, testcase_user=None): 
     return testcase_user 

    def get_user(self, user_id): 
     return User.objects.get(pk=user_id) 

然后,在测试过程中加yourapp.auth_backends.TestcaseUserBackendAUTHENTICATION_BACKENDS

AUTHENTICATION_BACKENDS = [ 
    "akindi.testing.auth_backends.TestcaseUserBackend", 
] 

然后,都灵g测试,你可以简单地打电话:

from django.contrib.auth import login 
user = User.objects.get(…) 
login(testcase_user=user) 
+0

优秀的答案。 –

+1

得到':login()得到了一个意外的关键字参数'testcase_user''有什么想法? – intelis

+0

您确定'login'来自'django.contrib.auth'(请参阅编辑后)?你确定后端被正确添加? –