Unittest.mock provides the stub to replace an external api call(HTTP request…) during the unittest. 

Mock and MagicMock create all attributes and methods for the Mock object . We can limit the return values and available attributes.

Mock provides the return_value and side_effects.  

i) return_value just return value when the particular method is called in the test. 

ii) side_effects allows you to perform some operations(like raising exceptions) and is helpful to call the patch call with different results in sequential order 

return_value gives the same result in the entire test. side effect will return the each value from the iterables one by one. (check the patch example code below)

Mock also providing the patch() function that can be used as a decorator or context manager.

It is easy to mock classes or objects in modules under test. The object you specify will be replaced with a mock and restored after the test ends.

How to choose mock or patch?.

Mock is useful when we want to pass the object as argument to other method or function. Check the below Mock example , complete object is mocked. We can mock the entire third party package or any package and test it.

Patch is useful when we want to mock some attributes method in a object(HTTP response, database calls, external api call) in method or function. Check the patch example in below code.

MOCK Example:

from unittest.mock import Mock

def external_api_call(api, args):
    # assume that's api is third party packages. 
    # it call the external api 
    return api.some_method(args)

def another_call(api, args):
   return api.another_method(args)

def test_api():
    api = Mock()
    api.some_method = Mock(return_value={})
    api.another_method = Mock(return_value={})
    another_call(api, '')
    external_api_call(api, 'args')

    # assertion will not through error

    api.another_method.assert_called_once()
    api.some_method.assert_called_with('args')

PATCH Example:

Note: patch needs  the actual path of the method. Here used in interpreter so __main__.patch_method. If it’s inside any class classname.patch_method

Side Effect Sample (instead of json response we can return Exception). Return_value is also the same as side_effect. Instead of side_effect attribute need to give the return_value

import json 
from unittest.mock import patch

def external_call(url):
    return json.dumps({})

def validate_json_response(response):
    try:
        json.loads(response)
    except Exception as e:
        return False
    else:
        return True

def sample_json_request():
    response1 = external_call('http://sample.com')
    response2 = external_call('http://example.com')

    if validate_json_response(response1) and validate_json_response(response2):
        return True

    return False

print(sample_json_request())

@patch('__main__.external_call')
def mock_external_call(mock_call):
    mock_call.side_effect = [json.dumps({}), json.dumps({})]
    response = sample_json_request()
    print(response==True)

Reference:

https://docs.python.org/3/library/unittest.mock.html

https://realpython.com/python-mock-library/