Mock is an object that simulates the behavior of other object. In python we have a builtin mock module in unittest library.

from unittest import mock
>>> m = mock.Mock()
# You can try to read some non-existing attribute - it will just return mock.
>>> m.some_attribute
<Mock name='mock.some_attribute' id='140126083485648'>

#  You can also try to call a method - it will return another mock too.
>>> m.process_data()
<Mock name='mock.process_data()' id='140126083843264'>

Mock have a return_value attribute to help you simulate specified behavior in tests. It allows to simply return a value.

>>> m = mock.Mock()
>>> m.process_data.return_value = 'The answer is 42'
>>> m.process_data()
'The answer is 42'
>>> m.process_data()
'The answer is 42'

You can assign anything - integers, string, tuples, dicts, classes, class instances, etc...

Side effect - a multifunctional tool

Mock's side_effect parameter allows to change the behavior of the mock. It accepts three types of values and changes its behavior accordingly.

side_effect = Exception

The mock will rise passed exception

>>> m.simulate_fail.side_effect = ValueError('Whoops...')
>>> m.simulate_fail()
Traceback (most recent call last):
[...]
File ".../lib/python3.8/unittest/mock.py", line 1140, in _execute_mock_call
    raise effect
ValueError: Whoops...

side_effect = Iterable

The mock will yield the values from this iterable on subsequent call

>>> m.my_attribute.side_effect = [5, 10, 42, ValueError('Something happened')]
>>> m.my_attribute()
5
>>> m.my_attribute()
10
>>> m.my_attribute()
42
>>> m.my_attribute()
Traceback (most recent call last):
[...]
File ".../lib/python3.8/unittest/mock.py", line 1140, in _execute_mock_call
    raise effect
ValueError: Something happened

side_effect = callable

The callable will be executed on each call with the parameters passed when calling the mocked method. Any callable will do, so it can be a function, or a class

# Class-based example 
class Person:
    def __init__(self, name):
        self.name = name

>>> m.my_attribute.side_effect = Person
>>> friend = m.my_attribute('Max')
>>> friend.name
'Max'
>>> repr(friend)
'<__main__.Person object at 0x7f71940ad2e0>'

# Function-based example
def log_calls(*args, **kwargs):
    print(f'Called with {args} and {kwargs}')

>>> m.another_attribute.side_effect = log_calls
>>> m.another_attribute()
Called with () and {}
>>> m.another_attribute(42, name='Peter', mood='Good')
Called with (42,) and {'name': 'Peter', 'mood': 'Good'}

Notes

pytest-mock - is a thin-wrapper around the mock package for easier use with pytest.