模拟外部 API POST 从测试视图 Python 视图调用
Mock external API POST call in view from test view Python
我有一个外部 API POST 调用是从我的 views.py
内部发出的:
class MyView(APIView):
def post(self, request):
my_headers = {
"Content-Type": "application/json"
}
response = requests.post("https://some-external-api.com", data=json.dumps(request.data), headers=my_headers)
return Response(status.response.status_code)
如您所见,这是一个非常简单的案例,使用接收到视图端点的相同数据对外部 API 进行 POST 调用。
现在,我正在尝试为此创建一个单元测试,同时模拟来自“https://some-external-api.com”的响应,所以我显然不必做一个实际的每次运行此单元测试时调用它。但是我遇到了困难,因为我无法让模拟方面工作,而且每次请求都被发送到实际的外部端点。
我知道网上有很多例子,但我试过的似乎都不起作用。我还没有看到模拟响应应该来自视图文件本身的示例。截至目前,我有这个:
@patch('requests.post')
def test_external_api_call(self, mock_post)
mock_post.return_value.ok = True
response = self.client.post(reverse('my-view'), {
//my random dummy json object goes here
}, format='json')
self.assertEqual(response.status_code, 200)
正如我所提到的,在上面的代码中,实际调用了“https://some-external-api.com”,而不是被模拟。
无需重新发明轮子,只需使用请求库可用的模拟程序,例如 requests_mock。
import json
import pytest
import requests
import requests_mock # python3 -m pip install requests-mock
def post():
my_headers = {"Content-Type": "application/json"}
my_data = {"some_key": "some_value"}
response = requests.post("https://some-external-api.com", data=json.dumps(my_data), headers=my_headers)
print(response.status_code, response.json())
@pytest.fixture
def mock_post():
with requests_mock.Mocker() as requests_mocker:
def match_data(request):
"""
This is just optional. Remove if not needed. This will check if the request contains the expected body.
"""
return request.json() == {"some_key": "some_value"}
requests_mocker.post(
"https://some-external-api.com", # Match the target URL.
additional_matcher=match_data, # Optional. If you want to match the request body too.
status_code=200, # The status code of the response.
json={"the_result": "was successful!"}, # Optional. The value when .json() is called on the response.
)
yield
def test_requests(mock_post):
post()
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
______________________________________________________________________________________________ test_requests ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
200 {'the_result': 'was successful!'}
1 passed in 0.04s
我有一个外部 API POST 调用是从我的 views.py
内部发出的:
class MyView(APIView):
def post(self, request):
my_headers = {
"Content-Type": "application/json"
}
response = requests.post("https://some-external-api.com", data=json.dumps(request.data), headers=my_headers)
return Response(status.response.status_code)
如您所见,这是一个非常简单的案例,使用接收到视图端点的相同数据对外部 API 进行 POST 调用。
现在,我正在尝试为此创建一个单元测试,同时模拟来自“https://some-external-api.com”的响应,所以我显然不必做一个实际的每次运行此单元测试时调用它。但是我遇到了困难,因为我无法让模拟方面工作,而且每次请求都被发送到实际的外部端点。
我知道网上有很多例子,但我试过的似乎都不起作用。我还没有看到模拟响应应该来自视图文件本身的示例。截至目前,我有这个:
@patch('requests.post')
def test_external_api_call(self, mock_post)
mock_post.return_value.ok = True
response = self.client.post(reverse('my-view'), {
//my random dummy json object goes here
}, format='json')
self.assertEqual(response.status_code, 200)
正如我所提到的,在上面的代码中,实际调用了“https://some-external-api.com”,而不是被模拟。
无需重新发明轮子,只需使用请求库可用的模拟程序,例如 requests_mock。
import json
import pytest
import requests
import requests_mock # python3 -m pip install requests-mock
def post():
my_headers = {"Content-Type": "application/json"}
my_data = {"some_key": "some_value"}
response = requests.post("https://some-external-api.com", data=json.dumps(my_data), headers=my_headers)
print(response.status_code, response.json())
@pytest.fixture
def mock_post():
with requests_mock.Mocker() as requests_mocker:
def match_data(request):
"""
This is just optional. Remove if not needed. This will check if the request contains the expected body.
"""
return request.json() == {"some_key": "some_value"}
requests_mocker.post(
"https://some-external-api.com", # Match the target URL.
additional_matcher=match_data, # Optional. If you want to match the request body too.
status_code=200, # The status code of the response.
json={"the_result": "was successful!"}, # Optional. The value when .json() is called on the response.
)
yield
def test_requests(mock_post):
post()
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
______________________________________________________________________________________________ test_requests ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
200 {'the_result': 'was successful!'}
1 passed in 0.04s