What is monkey patching and what are the risks?
Monkey patching is the practice of dynamically modifying or replacing attributes, methods, or modules at runtime — without altering the original source code. In Python, because everything is an object and objects are mutable, this is syntactically trivial: you assign a new function to an attribute of a class or module, and all subsequent calls to that attribute invoke your replacement.
The most common legitimate use is **test mocking**. Rather than making a real HTTP request in a unit test, you replace `requests.get` with a function that returns a fixed response: `requests.get = lambda url, **kw: MockResponse(200, data)`. The `unittest.mock.patch` decorator and context manager automate this pattern and restore the original after the test block exits, preventing test pollution.
Another use is **hotfixing third-party libraries** when you cannot wait for an upstream release — you override a buggy method on an imported class at application startup. This is risky and should be temporary.
The risks are substantial. **Hidden coupling**: code that reads the patched attribute has no knowledge of the substitution. If the patch is applied globally (not scoped to a test), all code in the process is affected. **Ordering dependency**: the patch must be applied before any code imports and caches a reference to the original; `from module import func` captures the original reference, bypassing a later `module.func = new_func` patch — a common source of confusing test failures. **Debugging difficulty**: a patched attribute does not appear in the class definition, making tracing broken behavior hard. **Fragility**: if the library being patched is updated and changes the patched method's signature, the patch silently continues with a mismatched interface.
In testing, `unittest.mock.patch` is the correct tool — it restores originals automatically, scopes the patch properly, and provides assertion capabilities. For production code, dependency injection is almost always a better alternative: pass the dependency as an argument rather than patching it globally. This makes the dependency explicit, testable, and auditable in code review.
Correctly defines monkey patching with an example and names testing as the primary use case. Identifies hidden coupling and debugging difficulty as risks.
Explains the `from module import func` gotcha (cached reference), discusses scoping via unittest.mock.patch vs. global patching, contrasts with dependency injection as the preferred production alternative, and can articulate why monkey patching violates the principle of least surprise.
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