Python Mock Requests

Summary: In this tutorial, you’ll learn how to mock the requests module in Python to test an API call using the unittest module.

The requests module is an HTTP library that allows you to send HTTP requests easily. Typically, you use the requests module to call an API from a remote server.

The scenario

For the demo purposes, we’ll use a public API provided by jsonplaceholder.typicode.com:

https://jsonplaceholder.typicode.com/Code language: Python (python)

To make an API call, you’ll use the requests method to send an HTTP GET method to the following end-point:

https://jsonplaceholder.typicode.com/albums/1Code language: Python (python)

It’ll return JSON data in the following format:

{
  "userId": 1,
  "id": 1,
  "title": "quidem molestiae enim"
}Code language: Python (python)

Since the requests module is not a built-in module, you need to install it by running the following pip command:

pip install requestsCode language: Python (python)

Making an API call using the requests module

The following defines a new module called album.py with a function find_album_by_id() that returns an album by an id:

import requests


def find_album_by_id(id):
    url = f'https://jsonplaceholder.typicode.com/albums/{id}'
    response = requests.get(url)
    if response.status_code == 200:
        return response.json()['title']
    else:
        return NoneCode language: Python (python)

How it works.

First, format the API end-point that includes the id parameter:

url = f'https://jsonplaceholder.typicode.com/albums/{id}'Code language: Python (python)

Second, call the get() function of the requests module to get a Response object:

response = requests.get(url)Code language: Python (python)

Third, call the json() method of the response object if the API call succeeds:

if response.status_code == 200:
   return response.json()['title']
else:
   return NoneCode language: Python (python)

The response.json() returns a dictionary that represents the JSON data.

Creating a test module

We’ll create a test_album.py test module that tests the functions in the album.py module:

import unittest

from album import find_album_by_id


class TestAlbum(unittest.TestCase):
   passCode language: Python (python)

Mocking the requests module

The find_album_by_id() function has two dependencies:

  • The get() method of the requests module
  • The Response object returned by the get() function.

So to test the find_album_by_id() function, you need to:

  • First, mock the requests module and call the get() function (mock_requests)
  • Second, mock the returned response object.

In other words, the mock_requests.get() returns a mock response object.

To mock the requests module, you can use the patch() function. Suppose that the mock_requests is a mock of the requests module.

The mock_requests.get() should return a mock for the response. To mock the response, you can use the MagicMock class of the unittest.mock module.

The following shows how to test the find_album_by_id() using the test_find_album_by_id_success() test method:

import unittest
from unittest.mock import MagicMock, patch

from album import find_album_by_id


class TestAlbum(unittest.TestCase):

    @patch('album.requests')
    def test_find_album_by_id_success(self, mock_requests):
        # mock the response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            'userId': 1,
            'id': 1,
            'title': 'hello',
        }

        # specify the return value of the get() method
        mock_requests.get.return_value = mock_response

        # call the find_album_by_id and test if the title is 'hello'
        self.assertEqual(find_album_by_id(1), 'hello')Code language: Python (python)

How it works.

First, patch the requests module as the mock_requests object:

@patch('album.requests')
def test_find_album_by_id_success(self, mock_requests):
    # ...Code language: Python (python)

Second, mock the response of the get() function using the MagicMock class. In this test method, we specify the status code 200 and return_value of the json() function as a hard-coded value:

mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
   'userId': 1,
   'id': 1,
   'title': 'hello',
}Code language: Python (python)

Third, use the mock_response as the return value of the get() function:

 mock_requests.get.return_value = mock_responseCode language: Python (python)

Finally, test if the title of the album is equal to the one that we specified in the return_value of the mock_response:

self.assertEqual(find_album_by_id(1), 'hello')Code language: Python (python)

Run the test:

python -m unittest -vCode language: Python (python)

Output:

test_find_album_by_id_success (test_album.TestAlbum) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.001s

OKCode language: Python (python)

By using the same technique, you can also test the find_album_by_id() function in the failed case:

import unittest
from unittest.mock import MagicMock, patch

from album import find_album_by_id


class TestAlbum(unittest.TestCase):

    @patch('album.requests')
    def test_find_album_by_id_success(self, mock_requests):
        # mock the response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            'userId': 1,
            'id': 1,
            'title': 'hello',
        }

        # specify the return value of the get() method
        mock_requests.get.return_value = mock_response

        # call the find_album_by_id and test if the title is 'hello'
        self.assertEqual(find_album_by_id(1), 'hello')

    @patch('album.requests')
    def test_find_album_by_id_fail(self, mock_requests):
        mock_response = MagicMock()
        mock_response.status_code = 400

        mock_requests.get.return_value = mock_response
        self.assertIsNone(find_album_by_id(1))Code language: Python (python)

Output:

test_find_album_by_id_fail (test_album.TestAlbum) ... ok
test_find_album_by_id_success (test_album.TestAlbum) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.002s

OKCode language: Python (python)

Summary

  • Use the patch() function to mock the requests module (mock_requests)
  • Use the MagicMock to mock the response returned by the mock_requests.get() function.
Did you find this tutorial helpful ?