pyguides

unittest.mock module

Overview

unittest.mock provides tools for replacing real objects in your tests with mock objects that you control. Mock a database, an HTTP client, or a filesystem call — you decide what the mock returns, and you can then assert that it was called with the arguments you expect.

Mocking is essential for testing code that depends on external services. You want fast, isolated tests that verify your code’s behavior without anything actually hitting the network or the disk.

unittest.mock is part of the standard library in Python 3.3+. A backport for older Python versions is available on PyPI as mock.

Mock Objects

The Mock class

Mock creates objects that record how they were used. Any attribute or method you access is created automatically and stored for later inspection:

from unittest.mock import Mock

mock = Mock()
mock.method(1, 2, key='value')
mock.attribute

mock.method.called          # => True
mock.method.call_count     # => 1
mock.method.call_args       # => call(1, 2, key='value')
mock.attribute              # => returns a new Mock

Configuring return values

Set return_value to control what the mock returns when called:

api = Mock()
api.fetch_user.return_value = {'id': 1, 'name': 'Alice'}

result = api.fetch_user(42)
result  # => {'id': 1, 'name': 'Alice'}

Specifying an interface with spec

Use spec to restrict the mock to the interface of a real class. Accessing undefined attributes raises AttributeError:

from unittest.mock import Mock
from collections import OrderedDict

mock = Mock(spec=OrderedDict)
mock.missing_method()
# => AttributeError: OrderedDict has no attribute 'missing_method'

MagicMock

MagicMock is a Mock subclass that pre-creates all magic methods. Use it when you need to mock objects that implement __str__, __len__, __iter__, or other dunder methods:

from unittest.mock import MagicMock

mock = MagicMock()
mock.__str__.return_value = 'custom string'

str(mock)  # => 'custom string'
mock['key']  # => returns a MagicMock

If you do not need magic methods, Mock is sufficient.

patch()

patch() replaces an attribute in a module or class for the duration of a test. It is the most common entry point for mocking in unit tests.

As a decorator

from unittest.mock import patch
import mymodule

@patch('mymodule.Database')
def test_save(MockDatabase):
    MockDatabase.return_value.query.return_value = [{'id': 1}]

    result = mymodule.get_data()

    MockDatabase.assert_called_once()
    assert result == [{'id': 1}]

The mock is passed as an argument to the decorated function. With nested decorators, mocks are passed bottom-up.

As a context manager

def test_save():
    with patch('mymodule.Database') as MockDatabase:
        MockDatabase.return_value.query.return_value = [{'id': 1}]
        result = mymodule.get_data()

    assert result == [{'id': 1}]

patch.object

patch.object patches a specific attribute on an object rather than in a module:

def test_timeout():
    obj = SomeClass()

    with patch.object(obj, 'timeout', 99):
        assert obj.timeout == 99

patch.dict

patch.dict temporarily sets values in a dictionary:

from unittest.mock import patch

config = {'host': 'localhost', 'port': 5432}

with patch.dict(config, {'port': 9000}):
    assert config['port'] == 9000

assert config['port'] == 5432  # restored

This is useful for mocking os.environ.

Side Effects

side_effect runs custom code when a mock is called, instead of returning a fixed value. It can be a function, an iterable, or an exception.

Raising exceptions

mock = Mock(side_effect=ValueError('something went wrong'))
mock()  # raises ValueError

Returning different values per call

Pass a list to return a different value on each call:

mock = Mock(side_effect=[1, 2, 3])

mock()  # => 1
mock()  # => 2
mock()  # => 3

Using a function as side effect

def fetch_remote(url):
    if 'fail' in url:
        raise ConnectionError('network error')
    return {'status': 'ok'}

mock = Mock(side_effect=fetch_remote)

mock('http://example.com')     # => {'status': 'ok'}
mock('http://fail.example.com')  # raises ConnectionError

Assertions

Mock objects record every call automatically:

mock = Mock()
mock.process(1, 2, key='value')

mock.assert_called_once()                    # fails if called more than once
mock.assert_called_with(1, 2, key='value') # fails if args differ
mock.assert_not_called()                   # fails if called at all

Inspect call history:

mock.method.call_count       # => 3
mock.method.call_args_list    # => [call(1), call(2), call(3)]

create_autospec

create_autospec creates a mock that mirrors the call signature of the real function or class. Calling it with wrong arguments fails with the same TypeError as the real function:

from unittest.mock import create_autospec
from mymodule import some_function

mock_func = create_autospec(some_function, return_value='mocked')

mock_func(1, 2)
mock_func.assert_called_once_with(1, 2)
mock_func(1)  # => TypeError: missing a required argument

Use autospec=True on patch() for the same effect as a decorator.

Common Use Cases

Mocking a database connection

@patch('mymodule.get_connection')
def test_query(MockConn):
    mock_conn = Mock()
    mock_conn.execute.return_value = [{'id': 1}]
    MockConn.return_value = mock_conn

    result = mymodule.run_query('SELECT * FROM users')

    MockConn.assert_called_once_with()
    mock_conn.execute.assert_called_once_with('SELECT * FROM users')

Mocking time

from unittest.mock import patch

with patch('time.sleep') as mock_sleep:
    my_function_that_delays()
    mock_sleep.assert_called_once_with(1)

Mocking environment variables

from unittest.mock import patch

with patch.dict('os.environ', {'API_KEY': 'test-secret'}):
    result = load_config()  # reads os.environ['API_KEY']
    assert result.api_key == 'test-secret'

Gotchas

Patching at the wrong location. You must patch where the object is looked up, not where it is defined:

# WRONG — patches the local name inside mymodule
@patch('mymodule.SomeClass')

# CORRECT — patches where SomeClass is used
@patch('production_code.SomeClass')

Mock is too permissive by default. A Mock accepts any attribute access silently. Use spec to restrict it to the real interface:

# Without spec — silent failure
mock = Mock()
mock.nonexistent_method()  # creates a new Mock, no error

# With spec — catches mistakes
mock = Mock(spec=RealClass)
mock.nonexistent_method()  # => AttributeError

Forgetting cleanup. Using patch as a decorator or context manager handles cleanup automatically. Using Mock directly for monkey-patching requires manual teardown.

See Also