Mocking with Pytest's monkeypatch
Pytest's `monkeypatch` is a temporary stunt double for your code, safely swapping out functions or environment variables for a single test. Use it to isolate tests from network calls or filesystem access.
WHY IT EXISTS Tests need to be fast, reliable, and isolated. Code that calls external APIs, connects to databases, or reads from the filesystem breaks these rules by introducing slow, unpredictable dependencies. The monkeypatch fixture was created to temporarily replace these unpredictable parts of your code with predictable fakes during a test run.
THE MENTAL MODEL Think of monkeypatch as a safe, temporary "stunt double" for parts of your Python environment. For one test, you can tell it: "Instead of calling the real requests.get, call this fake function that returns a canned JSON response." After the test finishes, pytest ensures the original requests.get is put back, leaving no side effects.
HOW IT WORKS By including monkeypatch as a test function argument, you get access to its methods. The most common is monkeypatch.setattr(target, name, value), where you specify the object to patch, the attribute name, and the replacement value (your mock). Other methods handle dictionary items (setitem) and environment variables (setenv). The pytest fixture mechanism guarantees that all changes are automatically reverted after the test concludes, even if it fails.
WHEN TO USE IT Use monkeypatch to isolate your code from external boundaries. Three common scenarios: first, replacing functions that make network calls or database queries (setattr); second, modifying global configuration loaded from a dictionary (setitem); third, setting environment variables needed for a specific test case (setenv). This makes your tests deterministic and fast.
WHEN NOT TO USE IT Avoid monkeypatch for testing interactions between your own internal components if you can achieve the same result with dependency injection. Overusing monkeypatching can make tests brittle and hard to understand, as they become tightly coupled to the implementation details you're patching over. It's for faking external systems, not for redesigning your internal logic on the fly.
ONE CANONICAL EXAMPLE To test a function that depends on the user's home directory, you can't rely on a specific path existing on the test runner. monkeypatch can force pathlib.Path.home() to return a predictable value. In a test, you would use monkeypatch.setattr(Path, "home", lambda: Path("/tmp/fake_home")). When your application code calls Path.home(), it will receive the fake path, making the test deterministic and independent of the environment it runs in.
Read the original → docs.pytest.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.