unittest.mock: Mock and MagicMock

RoadmapsPython

Overview

**Mock** objects are fake objects used in testing. They record how they are used and can pretend to return any value. **MagicMock** is a version of Mock that also supports Python's special dunder methods like `__len__` or `__str__`. Here is a worked example faking a payment gateway: ```python from unittest.mock import Mock # Create a fake gateway gateway = Mock() gateway.charge.return_value = 'Success' # Use it as if it was real result = gateway.charge(100) # Check what happened assert result == 'Success' gateway.charge.assert_called_with(100) ``` The `Mock` let us set a `return_value`. It also recorded that `charge` was called with `100`, which we verified using `assert_called_with`. Now, look at this faded example where one step is blank: ```python from unittest.mock import Mock api = Mock() api.fetch_user.___________ = {'name': 'Arjun'} assert api.fetch_user(1) == {'name': 'Arjun'} ``` To make the mock return the dictionary, we fill in the blank with `return_value`.

Testing code that depends on slow, broken, or expensive things (like real payment APIs or databases) is bad. Mocks let you test your logic safely by faking the outside world.

Where used: Unit tests with external dependencies

Why learn this

Code walkthrough

from unittest.mock import Mock

worker = Mock()
worker.compute.return_value = 42

ans = worker.compute('hard_math')
print(ans)
worker.compute.assert_called_with('hard_math')

Focus: worker.compute.return_value = 42

Aha moment

from unittest.mock import Mock

obj = Mock()
result = obj.this_method_does_not_exist()
print(type(result))

Prediction: What does this print?

Common guess: An AttributeError, because the method doesn't exist.

It prints `<class 'unittest.mock.Mock'>`. Mocks automatically create new child mocks when you access any attribute or method, even if they don't exist. They never raise an AttributeError by default.

Common mistakes

Recall questions

Understanding checks

Where is the bug in setting the return value?

The code calls `get_data(id=5)` before setting the return value.

You must attach `return_value` directly to the method reference (`my_api.get_data.return_value = 'Done'`). Calling the method creates a new mock object, so the setup is lost.

What happens when this code runs?

It raises an AssertionError because the mock was called with no arguments, not 10.

`assert_called_with` strictly checks the exact arguments used in the last call. Since `do_something()` had no arguments, the assertion fails.

Practice tasks

Verify the call

Given this code, add a line at the end to assert that the email service was called with `'admin@test.com'`.

Challenge

Set a return value and call it

Create a `Mock` called `db`. Make its `get_user` method return `'Admin'`. Then call `db.get_user(1)` and assign it to `user`.

Continue learning

Previous: Defining functions and return values

Previous: Class Creation and Instantiation

Next: patch as decorator and context manager

Return to Python Roadmap