Skip to content

Mocking and Patching with unittest.mock

diagram patch where the name is LOOKED UP, not where it is defined mermaid
from x import y copies the reference into the importing module's namespace. After that there are two names pointing at the same function, and replacing the original does nothing to the copy the code under test actually calls. This is the single most common reason a mock appears to be ignored.

You mock when a dependency is:

  • slow
  • flaky
  • external (network, API)
  • expensive to set up
service.py
import requests
 
 
def fetch_status(url: str) -> int:
    return requests.get(url, timeout=10).status_code
test_service.py
from unittest.mock import patch
 
import service
 
 
def test_fetch_status_mocked():
    with patch("service.requests.get") as get:
        get.return_value.status_code = 200
        assert service.fetch_status("https://example.com") == 200

autospec=True helps match real signatures.

patch_autospec.py
from unittest.mock import patch
 
 
def sample(a, b):
    return a + b
 
 
with patch("__main__.sample", autospec=True) as fn:
    fn.return_value = 10
    assert sample(1, 2) == 10
  • mock at the import location used by the code under test
  • keep mocks minimal; prefer real unit logic

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading