-
-
Save evansde77/45467f5a7af84d2a2d34f3fcb357449c to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
""" | |
mocking requests calls | |
""" | |
import mock | |
import unittest | |
import requests | |
from requests.exceptions import HTTPError | |
def google_query(query): | |
""" | |
trivial function that does a GET request | |
against google, checks the status of the | |
result and returns the raw content | |
""" | |
url = "https://www.google.com" | |
params = {'q': query} | |
resp = requests.get(url, params=params) | |
resp.raise_for_status() | |
return resp.content | |
class TestRequestsCall(unittest.TestCase): | |
""" | |
example text that mocks requests.get and | |
returns a mock Response object | |
""" | |
def _mock_response( | |
self, | |
status=200, | |
content="CONTENT", | |
json_data=None, | |
raise_for_status=None): | |
""" | |
since we typically test a bunch of different | |
requests calls for a service, we are going to do | |
a lot of mock responses, so its usually a good idea | |
to have a helper function that builds these things | |
""" | |
mock_resp = mock.Mock() | |
# mock raise_for_status call w/optional error | |
mock_resp.raise_for_status = mock.Mock() | |
if raise_for_status: | |
mock_resp.raise_for_status.side_effect = raise_for_status | |
# set status code and content | |
mock_resp.status_code = status | |
mock_resp.content = content | |
# add json data if provided | |
if json_data: | |
mock_resp.json = mock.Mock( | |
return_value=json_data | |
) | |
return mock_resp | |
@mock.patch('requests.get') | |
def test_google_query(self, mock_get): | |
"""test google query method""" | |
mock_resp = self._mock_response(content="ELEPHANTS") | |
mock_get.return_value = mock_resp | |
result = google_query('elephants') | |
self.assertEqual(result, 'ELEPHANTS') | |
self.assertTrue(mock_resp.raise_for_status.called) | |
@mock.patch('requests.get') | |
def test_failed_query(self, mock_get): | |
"""test case where google is down""" | |
mock_resp = self._mock_response(status=500, raise_for_status=HTTPError("google is down")) | |
mock_get.return_value = mock_resp | |
self.assertRaises(HTTPError, google_query, 'elephants') | |
if __name__ == '__main__': | |
unittest.main() |
Thank you!!! very clear and simple
👍
Hi, thanks for the gist. I have a question about the test_fail_query
function. Why it doesn't work if I change self.assertRaises(HTTPError, google_query, 'elephants')
to self.assertRaises(HTTPError, mock_get)
? Since the status code is 500. Shouldn't HTTPError be raised?
Hi, thanks for the gist. I have a question about the
test_fail_query
function. Why it doesn't work if I changeself.assertRaises(HTTPError, google_query, 'elephants')
toself.assertRaises(HTTPError, mock_get)
? Since the status code is 500. Shouldn't HTTPError be raised?
mock_get is just the call to request get that returns a response object, that response's raise_for_status method is what triggers the HTTPError, so the equivalent behaviour would be something like this:
@mock.patch('requests.get')
def test_failed_query(self, mock_get):
"""test case where google is down"""
mock_resp = self._mock_response(status=500, raise_for_status=HTTPError("google is down"))
mock_get.return_value = mock_resp
resp = mock_get()
self.assertRaises(HTTPError, resp.raise_for_status, 'elephants')
Hope that helps!
Great example. I wanted to know what difference would it make if we get rid of line 46 in the helper function. Will the following code not produce the same end result?
def _mock_response(
self,
status=200,
content="CONTENT",
json_data=None,
raise_for_status=None):
"""
since we typically test a bunch of different
requests calls for a service, we are going to do
a lot of mock responses, so its usually a good idea
to have a helper function that builds these things
"""
mock_resp = mock.Mock()
# mock raise_for_status call w/optional error
if raise_for_status:
mock_resp.raise_for_status.side_effect = raise_for_status
# set status code and content
mock_resp.status_code = status
mock_resp.content = content
# add json data if provided
if json_data:
mock_resp.json = mock.Mock(
return_value=json_data
)
return mock_resp
Thanks.
Thank you so much for this example.
Thank you
Thank you so much for this example.
Thank you
Thank you!!
Thank you!
it helped me a LOT, thanks so much.
Thank you
Hey @evansde77 : Really nice snippet to get the knowledge of mocking requests API calls with raise_for_status
scenario.
I would just recommend one thing here, instead of mocking actual request.get
library, we should add patch at mock_requests.request.get
. In this way, we are truly mocking actual object.
Let me know your thoughts on this!
Awsome example.. Thanks :)