从测试视图Python在视图中模拟外部API POST调用

2024-04-23 11:33:10 发布

您现在位置: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)

如您所见,这是一个非常简单的情况,即使用接收到views端点的相同数据对外部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“而不是被嘲笑


Tags: httpsselfcomapijsonresponsemystatus
1条回答
网友
1楼 · 发布于 2024-04-23 11:33:10

无需重新发明轮子,只需使用请求库可用的mocker,如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

相关问题 更多 >