2011-09-09 61 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'(請參閱編輯後)?你確定後端被正確添加? –