Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of mocking requests calls
#!/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()
@imrek

This comment has been minimized.

imrek commented May 1, 2017

Thank you for this example.

@curious-codr

This comment has been minimized.

curious-codr commented Sep 12, 2017

How to mock request object with json keyvalue pairs

@LucaoA

This comment has been minimized.

LucaoA commented Mar 29, 2018

Great

@malhotra18

This comment has been minimized.

malhotra18 commented Apr 4, 2018

Awsome example.. Thanks :)

@4lberto

This comment has been minimized.

4lberto commented Apr 25, 2018

Thank you!!! very clear and simple

@zerogvt

This comment has been minimized.

zerogvt commented Jul 23, 2018

👍

@Michael98Liu

This comment has been minimized.

Michael98Liu commented Aug 1, 2018

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?

@evansde77

This comment has been minimized.

Owner

evansde77 commented Sep 12, 2018

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?

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!

@saimkhan92

This comment has been minimized.

saimkhan92 commented Oct 4, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment