Reputation: 665
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
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