2016-01-21 67 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