在Python中,是否可以在另一个请求中模拟请求?

时间:2019-09-08 20:44:52

标签: python django mocking django-unittest

在Django中,我有一个向外部API发出请求的视图。该视图位于my_app中。

class ExternalAPIView(View):
    def get(self, request, *args, **kwargs):
        ...
        external_api_response = requests.get(settings.EXTERNAL_API_URL)
        ...

对于其单元测试,我对@patch装饰器的side_effect参数使用以下函数。

def mocked_requests_get_for_external_api(*args, **kwargs):
    class MockResponse:
        def __init__(self, content, status_code):
            self.content = content
            self.status_code = status_code

    if args[0] == settings.EXTERNAL_API_URL:
        return MockResponse(json.dumps('{"value": 1}'), 200)

    return MockResponse(None, 404)

...并且单元测试像这样没有问题:

@patch("my_app.views.requests.get", side_effect= mocked_requests_get_for_external_api)
def test_external_api(self, mock_get):
    response = self.client.get(settings.EXTERNAL_API_VIEW_URL)
    assert response.status_code == 200
    data = json.loads(response.content)
    assert data["value"] == 1

但是,我在同一项目中有另一个视图,该视图按如下方式调用此ExternalAPIView:

class MainView(View):
    def get(self, request, *args, **kwargs):
        ...
        response = requests.get(request.build_absolute_uri(settings.EXTERNAL_API_VIEW_URL))
        ...

我想为此MainView创建一个单元测试,它将通过settings.EXTERNAL_API_VIEW_URL进行对ExternalAPIView的调用,但是要在ExternalAPIView内部模拟外部API调用。

首先有可能吗?如果是这样,我该怎么办?

1 个答案:

答案 0 :(得分:0)

这可以通过仅模拟对requests.get的第二次调用并保留第一次调用来实现,例如:

import requests

@patch("my_app.views.requests.get", side_effect=[requests.get, mocked_requests_get_for_external_api])
def test_main_view_api(self, mock_get):
    response = self.client.get(MAIN_VIEW_URL)
    assert response.status_code == 200
    data = json.loads(response.content)
    assert data["value"] == 1