如何模拟在 __init__ 中实例化的 class 属性?
How to mock class attribute instantiated in __init__?
我正在尝试模拟 VKAuth 中的 "self.api.friends.get" 方法 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()
来自测试模块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)
在基于 SNView class 的视图中 post 调用 'auth-social' 期间创建了 VKAuth class 实例:
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()
但是在我们通过 self.client.post().
向 django-rest-framework api 发出请求之前模拟它
谢谢!
你打错了补丁。在 VKAuth
:
self.api = vk.API(self.session)
将 api
属性添加到 VKAuth
self
对象 。当你打电话
patch.object(accounts.auth_backends.vk_backend.VKAuth, 'api')
您正在修补 VKAuth
class 的 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)
备注:
- 仅当您真正知道为什么需要它时才使用
patch.object
而不是简单的 patch
.
autospec=True
不是强制性的,但 I strongly encourage to use it.
- 在
patch
上下文中 self.api
将等于 mock_api.return_value
因为调用 vk.API(self.session)
就像调用 mock_api()
;换句话说,mock_api
是用于替换 vk.API
引用的模拟对象。
- 看看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
我正在尝试模拟 VKAuth 中的 "self.api.friends.get" 方法 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()
来自测试模块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)
在基于 SNView class 的视图中 post 调用 'auth-social' 期间创建了 VKAuth class 实例:
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()
但是在我们通过 self.client.post().
向 django-rest-framework api 发出请求之前模拟它谢谢!
你打错了补丁。在 VKAuth
:
self.api = vk.API(self.session)
将 api
属性添加到 VKAuth
self
对象 。当你打电话
patch.object(accounts.auth_backends.vk_backend.VKAuth, 'api')
您正在修补 VKAuth
class 的 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)
备注:
- 仅当您真正知道为什么需要它时才使用
patch.object
而不是简单的patch
. autospec=True
不是强制性的,但 I strongly encourage to use it.- 在
patch
上下文中self.api
将等于mock_api.return_value
因为调用vk.API(self.session)
就像调用mock_api()
;换句话说,mock_api
是用于替换vk.API
引用的模拟对象。 - 看看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