Django单元测试-修补外部api的多个请求

Django单元测试-修补外部api的多个请求,django,Django,我需要用外部api编写“一个”测试代码,这需要“两次”请求 首先,我需要检查用户是否有效。 所以我在/users/utils.py import requests def login_decorator(func): def wrapper(self, request, *args, **kwargs): # first requests, which gives me an info about user. response = requests.g

我需要用外部api编写“一个”测试代码,这需要“两次”请求

首先,我需要检查用户是否有效。 所以我在/users/utils.py

import requests

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        # first requests, which gives me an info about user.
        response  = requests.get(
            'https://kapi.kakao.com/v2/user/me', 
            headers={'Authorization': 'Bearer access_token'}
        )

        request.user = response.json()['kakao_account']['email']
 
        return func(self, request, *args, **kwargs)

    return wrapper
import json
import requests

from utils import login_decorator


class BiddingView:
    #it uses login_decorator above
    @login_decorator
    def post(self, request, art_id):
        print(f"The current user is {request.user}")

        #second requests, with post method
        response = requests.post(
            'https://kapi.kakao.com/v2/api/talk/memo/default/send',
            headers = {'Authorization'   : 'Bearer token'},
            data    = {"template_object" : json.dumps({'message':'contents'})}
        )

        return response.text
导入请求
def登录装饰器(func):
def包装(self、request、*args、**kwargs):
#此访问令牌由外部api发布
access\u token=request.headers.get('Authorization',None)
#第一个请求,它为我提供了有关用户的信息。
response=requests.get(
'https://kapi.kakao.com/v2/user/me', 
headers={'Authorization':f'Bearer{access_token}}
)
user_email=response.json()['kakao_账户]['email']
request.user=user.objects.get(email=user\u email)
返回函数(self、request、*args、**kwargs)
返回包装器

然后,我需要再次向该用户发送一条带有外部api的消息。 此代码位于/bids/views.py

import requests

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        # first requests, which gives me an info about user.
        response  = requests.get(
            'https://kapi.kakao.com/v2/user/me', 
            headers={'Authorization': 'Bearer access_token'}
        )

        request.user = response.json()['kakao_account']['email']
 
        return func(self, request, *args, **kwargs)

    return wrapper
import json
import requests

from utils import login_decorator


class BiddingView:
    #it uses login_decorator above
    @login_decorator
    def post(self, request, art_id):
        print(f"The current user is {request.user}")

        #second requests, with post method
        response = requests.post(
            'https://kapi.kakao.com/v2/api/talk/memo/default/send',
            headers = {'Authorization'   : 'Bearer token'},
            data    = {"template_object" : json.dumps({'message':'contents'})}
        )

        return response.text
导入请求
类BiddingView(视图):
#它使用上面的login\u decorator
@登录装饰器
def post(自我、请求、艺术id):
尝试:
user=request.user
data=json.loads(request.body)
使用transaction.atomic():
#用招投标制度办事#
#外部api要求其令牌使用消息api。
token=request.headers.get('Authorization',None)
#第二个请求,使用post方法
response=requests.post(
'https://kapi.kakao.com/v2/api/talk/memo/default/send',
headers={'Authorization':f'Bearer{token}},
data={“template_object”:json.dumps({'message':'contents'})}
)
返回JsonResponse({'MESSAGE':'SUCCESS'},状态=200)
除KeyError外:
返回JsonResponse({'MESSAGE':'KEY ERROR'},状态=400)

这是我到目前为止关于BiddingView的单元测试代码,它显然只适用于decorator

@patch('users.utils.requests'))
def测试信息成功(自我、模拟请求):
类响应:
def json(self):
返回{'kakao_账户':{'email':'test@test.com'}}
mock_requests.get=MagicMock(返回值=MockResponse())
header={'HTTP\u Authorization':'ACCESS\u TOKEN'}
body={'offered_price':10000}
response=client.post(
“/bidding/1”,
json.dumps(body),
content_type='application/json',**标题
)
但是我需要为模拟测试同时修补.users.utils.requests.bids.views.requests

@patch('users.utils.requests')#+@patch('bids.views.requests'))
def测试信息成功(自我、模拟请求):

我想知道如何同时修补两个请求。

为了便于测试,我简化了您的源代码,以便我们能够集中精力解决外部请求的问题

/utils.py

import requests

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        # first requests, which gives me an info about user.
        response  = requests.get(
            'https://kapi.kakao.com/v2/user/me', 
            headers={'Authorization': 'Bearer access_token'}
        )

        request.user = response.json()['kakao_account']['email']
 
        return func(self, request, *args, **kwargs)

    return wrapper
import json
import requests

from utils import login_decorator


class BiddingView:
    #it uses login_decorator above
    @login_decorator
    def post(self, request, art_id):
        print(f"The current user is {request.user}")

        #second requests, with post method
        response = requests.post(
            'https://kapi.kakao.com/v2/api/talk/memo/default/send',
            headers = {'Authorization'   : 'Bearer token'},
            data    = {"template_object" : json.dumps({'message':'contents'})}
        )

        return response.text
/views.py

import requests

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        # first requests, which gives me an info about user.
        response  = requests.get(
            'https://kapi.kakao.com/v2/user/me', 
            headers={'Authorization': 'Bearer access_token'}
        )

        request.user = response.json()['kakao_account']['email']
 
        return func(self, request, *args, **kwargs)

    return wrapper
import json
import requests

from utils import login_decorator


class BiddingView:
    #it uses login_decorator above
    @login_decorator
    def post(self, request, art_id):
        print(f"The current user is {request.user}")

        #second requests, with post method
        response = requests.post(
            'https://kapi.kakao.com/v2/api/talk/memo/default/send',
            headers = {'Authorization'   : 'Bearer token'},
            data    = {"template_object" : json.dumps({'message':'contents'})}
        )

        return response.text
解决方案1-手动修补每个源文件的请求 可以一个接一个地堆叠unittest.mock.patch装饰器

from unittest.mock import MagicMock, patch

from views import BiddingView


class MockLoginResponse:
    def json(self):
        return {'kakao_account' : {'email' : 'test@test.com'}}


class MockViewResponse:
    text = "He alone, who owns the youth, gains the future."


@patch('utils.requests.get', MagicMock(return_value=MockLoginResponse()))
@patch('views.requests.post', MagicMock(return_value=MockViewResponse()))
def test_kakao_message_success():
    response = BiddingView().post(
        request=MagicMock(),
        art_id="some art"
    )
    print(f"Response: {response}")
输出:

__________________________________________________________________________________ test_kakao_message_success ___________________________________________________________________________________
------------------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------------------
The current user is test@test.com
Response: He alone, who owns the youth, gains the future.
解决方案2.1—不必为每个文件修补请求,而是修补准确的目标请求 这要求您安装库

输出:

__________________________________________________________________________________ test_kakao_message_success ___________________________________________________________________________________
------------------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------------------
The current user is test@test.com
Response: He alone, who owns the youth, gains the future.
  • 同上
解决方案2.2—不必为每个文件修补请求,而是修补精确的目标请求。但是现在,使用pytest的autouse特性将其自动应用于任何测试。 输出:

__________________________________________________________________________________ test_kakao_message_success ___________________________________________________________________________________
------------------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------------------
The current user is test@test.com
Response: He alone, who owns the youth, gains the future.
  • 同上