How do pytest fixtures, mocking, and patching work?
**Fixtures** are functions decorated with `@pytest.fixture` that pytest injects into test functions by parameter name. They handle setup and teardown via yield: code before yield runs before the test, code after yield runs after it regardless of outcome. Fixtures have scopes — function (default, re-created each test), class, module, session — that control how often the fixture is instantiated. Session-scoped fixtures are ideal for expensive resources like database connections. Fixtures can depend on other fixtures, letting you compose complex setups from small pieces. conftest.py files make fixtures available across a directory tree without explicit imports.
**Mocking** replaces real objects with `MagicMock` or `AsyncMock` instances that record calls and return configurable values. You create a mock, configure `mock.return_value` or `mock.side_effect`, pass it into the code under test, then assert on `mock.called`, `mock.call_args`, or `mock.call_count`.
**Patching** is how you inject mocks into code that creates its own dependencies internally. `unittest.mock.patch` temporarily replaces a name in a specific module's namespace. The key rule: patch where the name is looked up, not where it is defined. If `myapp.service` imports `requests` and uses `requests.get`, you patch `myapp.service.requests.get`, not `requests.get`.
patch can be used as a decorator, a context manager, or called manually with start/stop. The `pytest-mock` library exposes a `mocker` fixture that provides `mocker.patch()` with automatic teardown, which is cleaner than decorator stacking.
`side_effect` is more powerful than `return_value`: it can be a list of successive return values, an exception class to raise, or a callable that inspects arguments. Use side_effect when the mock needs to behave differently across calls or simulate failures.
For async code, use `AsyncMock` (Python 3.8+) so that awaiting the mock works correctly. A regular `MagicMock` used as a coroutine will raise a TypeError.
Explains fixtures with scope, uses patch correctly for a simple case, and knows the 'patch where imported' rule.
Articulates yield fixture teardown, compares mocker vs decorator stacking, explains side_effect vs return_value, and handles the async case.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment