deep-mock
deep-mock is a Python mocking library that simplifies patching and handles the edge cases that the standard unittest.mock.patch cannot solve. With patch you have to target the exact location a name was imported into, and even then it misses anything computed at import time or stored away in a closure, cache, or singleton. deep-mock lets you patch a dependency once and have it apply everywhere.
What it does
Its MockSysModules context manager replaces a function or class in its source module, then propagates the mock to every module that imported it and reloads those modules so any module-level state is recomputed with the mocked value. On exit, everything is restored and reloaded back to the real values. For indirect dependencies (a module that imports from a module that imports the mocked name), import_and_reload_module forces a reload at the right point.
It also ships conveniences for testing: a fake_useless_decorator pass-through to neutralize decorators with side effects (auth, caching, tracing like @observe or @firestore.transactional), project-wide defaults via DeepMockConfig in conftest.py, and helpers like find_calls_in_mock_calls and print_all_mock_calls for inspecting call history.
How it's used
Install it with pip install deep-mock, then wrap the code under test in MockSysModules with a list of (module, attribute, mock) tuples:
from unittest.mock import Mock
from deep_mock import MockSysModules
mock_fetch = Mock(return_value={"id": "1", "name": "Test User"})
with MockSysModules([
("myapp.database", "fetch_user", mock_fetch),
]):
from myapp.services import user_service
assert user_service.get_user("1")["name"] == "Test User"