When the same method is called multiple times in your code, you often need each call to behave differently — for example, fail first and then succeed on retry. Instead of writing multiple mocks or custom logic, you can use MagicMock.side_effect to define what happens on each consecutive call.
Using side_effect with a list
The simplest approach is to pass a list to side_effect. Each element in the list will be returned (or raised, if it's an exception) on successive calls:
from unittest.mock import MagicMock
mock = MagicMock()
mock.side_effect = [ValueError("First call fails"), "Success on second call"]
# First call raises ValueError
# Second call returns "Success on second call"
Using side_effect with a function
For more complex scenarios, you can pass a function to side_effect. The function will be called with the same arguments as the mock:
def custom_side_effect(*args, **kwargs):
if args[0] == "special":
return "Special response"
return "Default response"
mock.side_effect = custom_side_effect
Key Takeaways
Using side_effect keeps your tests clean and explicit about what should happen on each call, making retry logic and error handling much easier to test.