Reputation: 1913
I'm trying to mock the "self.api.friends.get" method in VKAuth class:
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()
from the test module 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)
having created instance of VKAuth class during the post call to 'auth-social' above in SNView class-based view:
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)
And I get an error:
AttributeError: <class 'accounts.auth_backends.vk_backend.VKAuth' doens't have the attribute 'api'
What should I write istead of the current patch.object to reach api.friends.get and mock it?
UPD:
To be more precise, I want some equivalent of:
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()
but mock it the moment before we make request to the django-rest-framework api via self.client.post().
Thank you!
Upvotes: 3
Views: 14410
Reputation: 23741
You are patching the wrong thing. In VKAuth
:
self.api = vk.API(self.session)
add api
attribute to VKAuth
self
object. When you call
patch.object(accounts.auth_backends.vk_backend.VKAuth, 'api')
you are patching the api
static attribute of VKAuth
class and not the object attribute.
You should patch vk.API
instead.
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)
Notes :
patch.object
only if you really know why you need it instead simple patch
.autospec=True
is not mandatory but I strongly encourage to use it.patch
context self.api
will be equal to mock_api.return_value
because call vk.API(self.session)
is like call mock_api()
; in other words mock_api
is the mock object used to replace the vk.API
reference.Now if you want fill your mock_api.return_value
by some behavior you can configure it in with
context:
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
Upvotes: 6