Python

Python mock multiple return values

25 September 2026 · 6 min read

Python mock multiple return values

Python’s flexibility and extensive libraries make it a popular choice for various programming tasks. When writing tests, effectively mocking dependencies is crucial for isolating units of code and ensuring reliable results. Mastering the art of mocking multiple return values in Python allows you to simulate complex scenarios and thoroughly test your code’s behavior under various conditions. This article delves into the intricacies of Python mocking, specifically focusing on how to configure mocks to return different values on successive calls. Learn how to leverage this powerful technique to create robust and comprehensive test suites.

Setting the Stage: Understanding Mock Objects

Mock objects are simulated objects that mimic the behavior of real objects in controlled ways. They’re particularly useful in testing when dealing with external dependencies, databases, or complex systems you don’t want to directly interact with during tests. Using mocks, you can isolate your code and test its logic independently of external factors. For instance, imagine testing a function that processes data fetched from an API. Instead of making real API calls, a mock object can simulate the API’s response, returning predefined data to ensure consistent test results. This not only speeds up testing but also prevents unexpected behavior caused by external system fluctuations.

The unittest.mock library (or mock in older Python versions) is the standard tool for creating mock objects in Python. It provides a versatile Mock class and other helpful utilities like patch for temporarily replacing real objects with mocks.

Mocking Multiple Return Values: The Basics

The side_effect attribute of the Mock object is your key to returning multiple values. By assigning an iterable (like a list or tuple) to side_effect, the mock will return each item in the iterable sequentially on successive calls. This allows you to simulate different responses, exceptions, or behaviors from the mocked object.

Example:

from unittest.mock import Mock mock_object = Mock() mock_object.side_effect = [1, 2, 3] print(mock_object()) Output: 1 print(mock_object()) Output: 2 print(mock_object()) Output: 3 

Handling Exceptions with side_effect

Beyond returning different values, side_effect can also be used to raise exceptions. This is useful for simulating error conditions and testing how your code handles them. Simply include the exception instance in the side_effect iterable.

Advanced Mocking Techniques

For more complex scenarios, you can use a callable as the side_effect. This allows you to dynamically generate return values based on the input arguments or other factors. This is particularly powerful for testing functions that interact with their dependencies in a stateful manner.

Example:

from unittest.mock import Mock def dynamic_side_effect(arg): if arg == 1: return "One" elif arg == 2: return "Two" else: raise ValueError("Invalid input") mock_object = Mock(side_effect=dynamic_side_effect) print(mock_object(1)) Output: One 

Using patch for Context Management

The patch decorator (or context manager) is essential for temporarily replacing real objects with mocks. This is vital for isolating specific parts of your code during testing without affecting other parts of your application.

Real-World Examples and Best Practices

Let’s consider a real-world scenario. Suppose you have a function that retrieves data from a database and processes it. Using side_effect, you can simulate different database responses, including successful queries, empty result sets, and even database errors, allowing for comprehensive testing.

  • Ensure your mocks accurately represent the behavior of the real objects they replace.
  • Focus on testing the logic of your code, not the behavior of external systems.

Another useful application is testing functions that interact with external APIs. You can mock the API calls and simulate various responses, including successful data retrieval, different HTTP status codes, and network errors.

  1. Import the necessary libraries.
  2. Define your test function.
  3. Use patch to mock external dependencies.
  4. Configure the mock’s side_effect.
  5. Make assertions to verify the expected behavior.

As Guido van Rossum, the creator of Python, once said, “Testing is crucial for ensuring code quality.” Mocking is an invaluable tool in any Python developer’s testing arsenal.

Learn more about Python testing.

[Infographic Placeholder]

Frequently Asked Questions

Q: What are some common use cases for mocking multiple return values?

A: Common uses include simulating different API responses, testing error handling, and testing stateful interactions with dependencies.

By mastering the techniques discussed in this article, you can significantly improve the quality and comprehensiveness of your Python test suites. Effective mocking leads to more robust and reliable code, giving you confidence in your software’s ability to handle a wide range of scenarios. Explore the provided resources and experiment with these techniques in your own projects to solidify your understanding. Dive deeper into Python testing best practices and advanced mocking strategies to elevate your testing game and build even more resilient applications. Consider exploring topics like patch decorators, MagicMock, and testing asynchronous code for a more comprehensive understanding of the Python testing landscape.

unittest.mock — mock object library — Python 3.11.5 documentation

Python Mock Library: How to Mock, Patch & Spy — Real Python

Newest ‘python-mock’ Questions - Stack Overflow

Question & Answer :
I am using pythons mock.patch and would like to change the return value for each call. Here is the caveat: the function being patched has no inputs, so I can not change the return value based on the input.

Here is my code for reference.

def get_boolean_response(): response = io.prompt('y/n').lower() while response not in ('y', 'n', 'yes', 'no'): io.echo('Not a valid input. Try again']) response = io.prompt('y/n').lower() return response in ('y', 'yes') 

My Test code:

@mock.patch('io') def test_get_boolean_response(self, mock_io): #setup mock_io.prompt.return_value = ['x','y'] result = operations.get_boolean_response() #test self.assertTrue(result) self.assertEqual(mock_io.prompt.call_count, 2) 

io.prompt is just a platform independent (python 2 and 3) version of “input”. So ultimately I am trying to mock out the users input. I have tried using a list for the return value, but that doesn’t seam to work.

You can see that if the return value is something invalid, I will just get an infinite loop here. So I need a way to eventually change the return value, so that my test actually finishes.

(another possible way to answer this question could be to explain how I could mimic user input in a unit-test)


Not a dup of this question mainly because I do not have the ability to vary the inputs.

One of the comments of the Answer on this question is along the same lines, but no answer/comment has been provided.

You can assign an iterable to side_effect, and the mock will return the next value in the sequence each time it is called:

>>> from unittest.mock import Mock >>> m = Mock() >>> m.side_effect = ['foo', 'bar', 'baz'] >>> m() 'foo' >>> m() 'bar' >>> m() 'baz' 

Quoting the Mock() documentation:

If side_effect is an iterable then each call to the mock will return the next value from the iterable.