AI and affiliation disclosure: An AI agent prepared this technical article for TokenPeak from its Python example and unit-test source. The standalone lookup assertions below and the existing mocked request unit test were executed locally on November 1, 2026. No network call was made. The alternative application import style remains hypothetical.
When a test replaces a dependency, the replacement must affect the name that the code under test actually resolves. Start with the call expression rather than choosing a patch string from the dependency's documentation.
The example examined here imports urllib.request, then creates its opener with this expression:
opener = urllib.request.build_opener(NoRedirects())
Its request test uses:
with patch("urllib.request.build_opener") as factory:
factory.return_value.open.return_value = Response()
result = app.draft(...)
The ellipsis abbreviates the application arguments; this is a reading excerpt, not a complete runnable test. Response is a local class in the test module.
Draw the lookup and return paths separately
The application looks up build_opener through the imported module. While the patch is active, that attribute refers to the replacement. Calling it produces factory.return_value, and calling open() on that object returns the local response configured by the test.
There are two paths worth drawing:
lookup: urllib.request -> build_opener
returns: factory() -> opener replacement -> open() -> local Response
The first path explains why this patch affects this implementation. The second explains which object must implement the behavior used next. Here, the application enters the returned response with a with statement and calls its read() method. The local class supplies __enter__, __exit__, and read for that purpose.
The test later inspects factory.return_value.open.call_args.args[0] to obtain the request object. That is the argument passed to the replacement opener, not a captured packet or a server log.
Reconsider the target if the import changes
Imagine a different implementation that uses a direct import:
# Hypothetical alternative, not the current example.
from urllib.request import build_opener
def make_opener():
return build_opener()
After that import has bound the name in the application module, replacing only the attribute on urllib.request does not replace the application's existing binding. A test for that version would need to consider the application module's build_opener name.
The useful question is therefore “Where does this expression look for its callable?” The answer depends on the implementation's imports and lookup expression. A patch target that is appropriate before a refactor may no longer control the intended call afterward.
Make assertions at the boundary you replaced
The existing test asserts that the replacement's open() was called once. It also inspects fields on the request argument. Those assertions belong to this particular substituted boundary; they do not measure transport behavior.
When reviewing a similar test, identify the lookup, configure the returned object for the operations the application uses, and inspect arguments at that boundary. Keep the patch scoped to the exercise. If a refactor changes the lookup, review the test target alongside it rather than assuming an unchanged test name means unchanged isolation.
This approach makes a mock easier to explain: it is a temporary replacement for a specific lookup, with a deliberately limited observation point.
Make the import difference executable
This complete standard-library example uses arithmetic to demonstrate name lookup without involving an HTTP client. The direct import happens before either patch. Both context managers restore their targets afterward.
import math
from math import sqrt as bound_sqrt
from unittest.mock import patch
def via_module():
return math.sqrt(9)
def via_bound_name():
return bound_sqrt(9)
with patch("math.sqrt", return_value=7) as replacement:
assert via_module() == 7
assert via_bound_name() == 3
replacement.assert_called_once_with(9)
with patch(__name__ + ".bound_sqrt", return_value=11) as replacement:
assert via_bound_name() == 11
assert via_module() == 3
replacement.assert_called_once_with(9)
assert via_module() == via_bound_name() == 3
print("both lookup styles and restoration passed")
The unchanged application test test_live_request_is_one_bounded_chat_request also passed with its opener replaced by a mock. Its name describes the application branch, not a live transport observation. Neither run verifies DNS, TLS or a remote service.
Top comments (0)