Mock multiple return values in a Python unit Test

avatar
Borislav Hadzhiev

Last updated: Apr 11, 2024
3 min

banner

# Table of Contents

  1. Mock multiple return values in a Python unit Test
  2. Using the patch() function decorator to return multiple values from a Mock

# Mock multiple return values in a Python unit Test

Set the side_effect attribute of the Mock object to a list containing the values to mock multiple return values in a Python unit test.

When the side_effect attribute is set to an iterable, each call to the mock returns the next value in the iterable.

main.py
from unittest.mock import Mock m = Mock() m.side_effect = ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com

mock multiple return values in python

If you need to return multiple values from a Python Mock (e.g. a list), set the return_value attribute to a list.

main.py
from unittest.mock import Mock m = Mock() m.return_value = ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ ['bobby', 'hadz', 'com']

return multiple values from python mock

We used the unittest.mock.Mock() class to create a new Mock object.

The side_effect attribute can be set to an iterable, a function to be called when the mock is called or an exception to be raised.

We set the side_effect attribute to a list containing 3 items we want to return from the Mock().

main.py
from unittest.mock import Mock m = Mock() m.side_effect = ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com

When side_effect is set to an iterable, each call to the Mock returns the next value in the iterable.

You can also pass the return values list to the Mock class upon instantiation.

main.py
from unittest.mock import Mock # ๐Ÿ‘‡๏ธ passing side_effect list upon instantiation m = Mock(side_effect=['bobby', 'hadz', 'com']) print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com

The code sample achieves the same result.

You can also supply the side_effect argument when instantiating the MagicMock() class.

main.py
from unittest.mock import MagicMock m = MagicMock(side_effect=['bobby', 'hadz', 'com']) print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com

The MagicMock class is a subclass of Mock with default implementations for most magic methods.

When you use the MagicMock class, you don't have to configure the magic methods yourself.

If you exhaust the iterator, a StopIteration error is raised.

main.py
from unittest.mock import Mock m = Mock() m.side_effect = ['bobby', 'hadz', 'com'] print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com # โ›”๏ธ StopIteration print(m())

You can use the itertools built-in module if you want to return a specific value after the iterator has been exhausted instead of raising a StopIteration error.

main.py
from unittest.mock import Mock import itertools m = Mock() m.side_effect = itertools.chain( ['bobby', 'hadz'], itertools.repeat('com') ) print(m()) # ๐Ÿ‘‰๏ธ bobby print(m()) # ๐Ÿ‘‰๏ธ hadz print(m()) # ๐Ÿ‘‰๏ธ com print(m()) # ๐Ÿ‘‰๏ธ com print(m()) # ๐Ÿ‘‰๏ธ com print(m()) # ๐Ÿ‘‰๏ธ com

Instead of raising a StopIteration error, we return the string "com" after the iterator is exhausted.

return default value after iterator exhausted

# Using the patch() function decorator to return multiple values from a Mock

You can also use the patch() function decorator to return multiple values from a Mock.

Suppose we have the following example.py file.

example.py
def greet(name): return f'hello {name}'

Here is an example of mocking the example.greet function with multiple return values.

main.py
from unittest.mock import patch import example @patch('example.greet', side_effect=['hello Alice', 'hello Bobby', 'hello Carl']) def test_greet_function(greet_patched): assert example.greet('Alice') == 'hello Alice' assert example.greet('Bobby') == 'hello Bobby' assert example.greet('Carl') == 'hello Carl' print(greet_patched) print(greet_patched.called) assert greet_patched is example.greet assert greet_patched.called assert greet_patched.call_count == 3 test_greet_function()

multiple mock return values with patch decorator

We used the patch() function decorator to patch the greet function from the example module.

The first argument the patch() function takes should be a string in the form of package.module.functionName or package.module.ClassName.

The target must be importable from the environment in which you are calling patch().

We passed the side_effect sequence of return values to the @patch() function.

main.py
@patch('example.greet', side_effect=['hello Alice', 'hello Bobby', 'hello Carl'])

Calls to the example.greet() method will return the items from the sequence one after the other.

main.py
@patch('example.greet', side_effect=['hello Alice', 'hello Bobby', 'hello Carl']) def test_greet_function(greet_patched): assert example.greet('Alice') == 'hello Alice' assert example.greet('Bobby') == 'hello Bobby' assert example.greet('Carl') == 'hello Carl'

The decorated function gets passed the mock object.

You can assert that the mock has been called, how many times it has been called, etc.

main.py
print(greet_patched) print(greet_patched.called) assert greet_patched is example.greet assert greet_patched.called assert greet_patched.call_count == 3

Here is an example of asserting that the mock was called with specific arguments.

main.py
from unittest.mock import patch import example @patch('example.greet', side_effect=['hello Alice', 'hello Bobby', 'hello Carl']) def test_greet_function(greet_patched): assert example.greet('Alice') == 'hello Alice' greet_patched.assert_called_with('Alice') assert example.greet('Bobby') == 'hello Bobby' greet_patched.assert_called_with('Bobby') assert example.greet('Carl') == 'hello Carl' greet_patched.assert_called_with('Carl') print(greet_patched) print(greet_patched.called) test_greet_function()

assert mock called with specific arguments

I've also written a detailed guide on how to assert that Mock was called with specific arguments.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev