2016-01-21 29 views
0

我試圖嘲弄在VKAuth類中的 「self.api.friends.get」 的方法:如何模擬__init__中實例化的類屬性?

import vk 

class VKAuth(object): 
    def __init__(self, access_token, user): 
     self.session = vk.Session(access_token = access_token) 
     self.api = vk.API(self.session) 

    def follow(self): 
     vk_friends = self.api.friends.get() 

從測試模塊test_views.py:

from mock import patch 
from ..auth_backends.vk_backend import VKAuth 

class AddUsersToList(TestCase): 
    def test_auth_vk(self, mock_get): 
     ... etc ... 
     auth_token = 'ceeecdfe0eb4bf68ceeecdfe0eb4bf68ceeecdfe0eb4bf68652530774ced6cbc8cba0' 
     token = user.auth_token.key 
     self.client.defaults['HTTP_AUTHORIZATION'] = 'Token {}'.format(token) 
     with patch.object(accounts.auth_backends.vk_backend.VKAuth, 'api'): #point where we're mocking 
      response = self.client.post(reverse('auth-social', kwargs=dict(backend='vk')), dict(access_token=auth_token), follow=True) 

已經創建VKAuth實例後調用在類的權威性,社會「上述SNView基於類的觀點:

class SNView(generics.GenericAPIView): 
    serializer_class = serializers.AuthSocialSerializer 
    permission_classes = (rest_permissions.IsAuthenticated) 

    def post(self, request, backend, *args, **kwargs): 
     s = self.get_serializer(data=request.DATA) 

     if s.is_valid(): 
      auth_backends = { 
       'vk': VKAuth, 
       'facebook': FBAuth 
      } 

      if backend in auth_backends: 
       auth_backend = auth_backends[backend](access_token=s.data['access_token'], user=self.request.user) 

我得到一個錯誤:

AttributeError: <class 'accounts.auth_backends.vk_backend.VKAuth' doens't have the attribute 'api' 

我應該寫什麼,而不是當前patch.object到達api.friends.get並模擬它?

UPD:

更確切地說,我想的一些等價的:

auth_token = 'ceeecdfe0eb4bf68ceeecdfe0eb4bf68ceeecdfe0eb4bf68652530774ced6cbc8cba0' 
    user = User.objects.get(id = 2) 
    vk_auth = VKAuth(auth_token, user) 

    vk_ids=[111111,2222222,3333333,44444444] 
    vk_auth.authenticate() 
    vk_auth.api.friends = MagicMock(name='get', return_value=None) 
    vk_auth.api.friends.get = MagicMock(name='get', return_value=vk_ids) 
    data = vk_auth.follow() 

但嘲笑它的那一刻,我們也求通過自Django的休息框架API之前.client.post()。

謝謝!

回答

2

你正在修補錯誤的東西。在VKAuth

self.api = vk.API(self.session) 

附加api屬性VKAuthself對象。當你調用

patch.object(accounts.auth_backends.vk_backend.VKAuth, 'api') 

要修補VKAuth類的靜態api屬性而不是對象的屬性。

您應該修補vk.API

with patch('vk.API', autospec=True) as mock_api: 
    response = self.client.post(reverse('auth-social', kwargs=dict(backend='vk')), dict(access_token=auth_token), follow=True) 

注:

  1. 使用patch.object只有當你真正知道爲什麼你需要它,而不是簡單patch
  2. autospec=True不是強制性的,而是I strongly encourage to use it
  3. patch上下文self.api將等於mock_api.return_value因爲呼叫vk.API(self.session)是像呼叫mock_api();換句話說mock_api是用於替代vk.API參考的模擬對象。
  4. 看一看where to patch,你會發現它非常有用。

現在如果你想填補一些行爲的mock_api.return_value您可以在with方面進行配置:

with patch('vk.API', autospec=True) as mock_api: 
    m_api = mock_api.return_value 
    m_api.friends.return_value = None 
    m_api.friends.get.return_value = vk_ids 
    .... Your test 
+0

在我的情況下,它返回:AttributeError的:模仿對象有沒有屬性「朋友」 – paus

+0

刪除autospec = 類API(對象):在vk.API我看到了真正的 –

+0

裏面 ... 高清__getattr __(自我,METHOD_NAME): 退貨請求(個體經營,METHOD_NAME) 類請求(對象): __slots__ =( '_api', '_method_name', '_method_args') DEF __init __(個體,API,METHOD_NAME): self._api = API self._method_name = METHOD_NAME DEF __getattr __(個體,METHOD_NAME): 返回請求(self._api,self._method_name + + METHOD_NAME '') DEF __call __(個體,** method_args): self._method_args = method_args 返回self._api._session .make_request(self) – paus

相關問題