iuysal
iuysal

Reputation: 665

In Python, is it possible to mock requests inside another request?

In Django, I have a view which makes a request to an external API. The view is in my_app.

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

For its unit tests, I use the following function for the side_effect parameter of the @patch decorator.

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)

... and the unit test goes like this without an issue:

@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

However, I have another view in the same project, which calls this ExternalAPIView as follows:

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

I'd like to create a unit test for this MainView, which will make the call to the ExternalAPIView through settings.EXTERNAL_API_VIEW_URL, but mock external API call inside the ExternalAPIView.

Is it possible at the first place? And if so, how can I do that?

Upvotes: 2

Views: 825

Answers (1)

ipaleka
ipaleka

Reputation: 3967

This could be achieved by mocking only the second call to requests.get and leaving the first call as is, something like:

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

Upvotes: 1

Related Questions