2016-08-04 65 views
0

我目前正在寫一個單元測試以下get_can_edit功能在我的串行:Django的REST框架 - 單元測試錯誤

def get_can_edit(self, obj): 
    request = self.context.get('request') 
    user = User.objects.get(username=request.user) 
    return user == obj.admin 

在我的測試,我調用該函數在這裏:

def test_get_can_edit(self): 
    self.request1 = RequestFactory().post('./fake_path') 
    self.request1.user = SimpleLazyObject(self.user1) 
    self.request1.query_params = {} 
    self.serializer1 = ConferenceSerializer(context={'request': self.request1}) 
    self.canEdit1 = self.serializer1.get_can_edit(self.conference) 

當我運行測試時,它失敗了錯誤:'User' object is not callable,並參考以下行中的串行器get_can_edit函數:

user = User.objects.get(username=request.user) 

然而,在瀏覽器中運行時,該功能get_can_edit正確執行,並沒有問題,「用戶」是客體可調用。

我原本以爲我創建的假數據的格式有問題(我使用factory_boyRequestFactory來創建假數據)。使用調試器,我通過調用測試並通過服務器發出真正的請求來進入get_can_edit函數。在這兩種情況下,request.userobj.admin是在正確的形式,所以我排除了數據格式錯誤。

接下來,我在調試器試圖

User.objects.get(username=request.user) 

。它對服務器中的真實請求起作用,並且在測試中返回與假請求相同的'User' object is not callable錯誤。我做了一個快速堆棧溢出/谷歌搜索在Django object is not callable錯誤,但它看起來像其他情況下,通過確保模型正確,導入(我是絕對正確導入)得到了解決。

所以在這一點我知道,有一個與我的測試情況下一個問題,即不與實際要求存在,但我真的不能弄清楚它是什麼,我跑出來的想法。

全碼:

The serializer

The test

非常感謝,讓我知道,如果有去了解這樣的一個更簡單的方法。



UPDATE: 於是我又回到了兩種不同的調試器,做User.objects.all()。具有真實請求的服務器中的用戶返回了正確的用戶列表。與虛假請求測試中的那個人剛剛返回anonymoususer。因爲我使用factory_boy來創建我的假用戶,所以django在User.objects中找不到它。

有人告訴我,不要讓真正的請求在我的單元測試,所以創建一個實際的用戶是不可能的。

我也試圖改變get_can_edit功能不檢查User.objects.request.user是包含用戶的SimpleLazyObject。我試着做的是request.user.id並將其與obj.admin.id進行比較,但顯然當您對SimpleLazyObject做任何事情時,都會諮詢User.objects以找到與其關聯的實際用戶,因此它仍然具有相同的錯誤'User' object is not callable

因此,底線是這樣的:我需要一個假的用戶添加到User.objects沒有作出真正的請求

+1

您正在使用'app.models.User'和'django.contrib.auth.model.User'。這是什麼原因?你還可以發佈相關模型嗎? –

+0

他們是相同的模型...我不知道他們爲什麼導入不同(我不是這些網頁上的唯一合作者),但我只是試着改變他們導入的方式,同樣的問題。 用戶模型文檔位於:https://docs.djangoproject.com/en/1.9/topics/auth/default/ – Tom

回答

1

正是在這裏解決:需要Django REST Framework - Fake objects for unit tests

基本上factory_boy工廠進行不同的設置。當我定義我的工廠,我有以下行:

class UserFactory(factory.Factory): 

但很顯然,而非factory.Factory,它應該說factory.DjangoModelFactory像這樣:

class UserFactory(factory.DjangoModelFactory): 

這是一個有點討厭,因爲factory_boydocumentationfactory.Factory的第一頁上的示例,但稍後會告訴您使用DjangoModelFactory。我想這就是我不應該徹底閱讀文檔所應得的。

2

這是更好,以便在所有測試中使用它來創建一個基類。此類還包含支持HTTP方法的APIClient DRF類,並且您不需要手動創建Request對象。

from rest_framework.test import APITestCase 

class BaseAPITestCase(APITestCase): 
    """ 
    Base class to initialize the test cases 
    """ 

    self.user = YourUserFactory.create_batch(1) 
    self.user_client = self.get_client(user=self.user) 

在您的測試

class YourTestClass(BaseAPITestCase): 

    def test_get_can_edit(self): 
     response = self.user_client.post('./fake_path') 
     # proccess your response