0Pricing
Python Academy · Lesson

Mocking with unittest.mock

Isolate units under test by mocking dependencies.

Mocking with unittest.mock is a free Python Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Mock?

Mocks replace real dependencies (databases, APIs, file system) with controllable fakes so tests run fast, deterministically, and in isolation.

from unittest.mock import Mock

api = Mock()
api.get_user.return_value = {"id": 1, "name": "Alice"}

result = api.get_user(1)
print(result)  # {'id': 1, 'name': 'Alice'}

Mock and MagicMock

Mock is the base class. MagicMock auto-configures magic/dunder methods so it can be used as iterators, context managers, etc.

from unittest.mock import MagicMock

m = MagicMock()
m.__len__.return_value = 5
print(len(m))  # 5

m.__iter__.return_value = iter([1, 2, 3])
for x in m:
    print(x)

patch as Decorator

Use @patch to replace an object in a module with a mock for the duration of the test.

from unittest.mock import patch

def get_data():
    import requests
    return requests.get("https://api.example.com").json()

@patch("requests.get")
def test_get_data(mock_get):
    mock_get.return_value.json.return_value = {"key": "value"}
    result = get_data()
    assert result == {"key": "value"}

patch as Context Manager

Use patch() as a context manager for more localised mocking.

from unittest.mock import patch

def test_open():
    with patch("builtins.open", create=True) as mock_open:
        mock_open.return_value.__enter__.return_value.read.return_value = "data"
        with open("file.txt") as f:
            assert f.read() == "data"

patch.object

patch.object(target, attribute) patches a specific attribute on an existing object or class.

from unittest.mock import patch
import mymodule

def test_method():
    with patch.object(mymodule.MyClass, "fetch", return_value=42):
        obj = mymodule.MyClass()
        assert obj.fetch() == 42

Asserting Calls

Mocks record every call. Use assert_called_once_with, assert_called_with, and call_count to verify behaviour.

from unittest.mock import Mock

send = Mock()
send("hello", to="alice")

send.assert_called_once_with("hello", to="alice")
print(send.call_count)  # 1

return_value and side_effect

Set return_value to control what the mock returns. Use side_effect to raise exceptions or return different values on successive calls.

from unittest.mock import Mock

m = Mock(side_effect=[1, 2, ValueError("done")])
print(m())  # 1
print(m())  # 2
m()         # raises ValueError

spec: Type-Safe Mocks

Pass spec=MyClass to restrict the mock to only attributes that exist on the real class.

from unittest.mock import Mock

class Calc:
    def add(self, a, b): return a + b

m = Mock(spec=Calc)
m.add(1, 2)         # OK
# m.subtract(1, 2)  # AttributeError: Mock does not have 'subtract'

patch.dict

Use patch.dict to temporarily modify a dictionary (e.g., environment variables or module-level configs).

from unittest.mock import patch
import os

def test_env():
    with patch.dict(os.environ, {"DEBUG": "true"}):
        assert os.environ["DEBUG"] == "true"
    assert "DEBUG" not in os.environ

Mock in pytest with pytest-mock

pytest-mock provides a mocker fixture that wraps unittest.mock and auto-tears down after each test.

# pip install pytest-mock

def test_service(mocker):
    mocker.patch("mymodule.requests.get", return_value=mocker.Mock(
        json=lambda: {"status": "ok"}
    ))
    from mymodule import call_api
    assert call_api()["status"] == "ok"

AsyncMock for Coroutines

Use AsyncMock to mock async functions that are awaited.

from unittest.mock import AsyncMock, patch
import asyncio

async def fetch():
    import httpx
    async with httpx.AsyncClient() as c:
        r = await c.get("https://example.com")
        return r.json()

def test_fetch():
    with patch("httpx.AsyncClient.get", new_callable=AsyncMock) as m:
        m.return_value.json.return_value = {"ok": True}
        result = asyncio.run(fetch())
        assert result["ok"] is True

Quick Check

What attribute do you set on a Mock to control what value it returns when called?

Recap

unittest.mock provides Mock, MagicMock, patch, and AsyncMock. Use return_value and side_effect to control behaviour, and assertion methods to verify how mocks were called.

Frequently asked questions

Is the “Mocking with unittest.mock” lesson free?

Yes — the full text of “Mocking with unittest.mock” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.

What will I learn in “Mocking with unittest.mock”?

Isolate units under test by mocking dependencies. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Python Academy?

No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Mocking with unittest.mock” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Python Academy lesson?

Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Writing Your First pytest Tests
  2. Fixtures and Setup/Teardown
  3. Parametrize and Test Coverage
  4. Mocking with unittest.mock
← Back to Python Academy