Python Interview Questions on Mocking and Failure Tests
A useful mock isolates a dependency while keeping the behavior under test visible. Python interview questions about mocking often ask where to patch, what an assertion proves and which failure a test could miss. Start with the real unit's contract rather than replacing every collaborator by default.
By Ravindra Wadile · Published

645 words · About 3 min read
A useful mock isolates a dependency while keeping the behavior under test visible. Python interview questions about mocking often ask where to patch, what an assertion proves and which failure a test could miss. Start with the real unit's contract rather than replacing every collaborator by default.
The following Python 3 example uses only the standard-library mock library. The notification function is local and fictional. No real message is sent.
What behavior is actually under test?
Suppose a small dispatcher should retry once after a timeout, return a successful result and avoid a third call. A test needs to check those three things. Merely asserting that a mock exists does not check the retry policy.
from unittest.mock import Mock, call
def dispatch(send, message):
for attempt in range(2):
try:
return send(message)
except TimeoutError:
if attempt == 1:
raise
sender = Mock(side_effect=[TimeoutError("slow"), "accepted"])
assert dispatch(sender, "hello") == "accepted"
assert sender.call_args_list == [call("hello"), call("hello")]
failed = Mock(side_effect=TimeoutError("still slow"))
try:
dispatch(failed, "hello")
except TimeoutError:
pass
else:
raise AssertionError("Failure was hidden")
assert failed.call_count == 2
The side-effect list makes the first call fail and the second succeed. The second test confirms that two failures escape to the caller. Both are needed: a success-only test could accept code that retries forever or quietly hides a final failure.
Why inject the sender in this example?
Passing the dependency explicitly makes its boundary clear. The dispatcher owns retry decisions; the sender owns delivery. This makes the small unit easy to test without patching module state.
It does not prove a production delivery retry is safe. A sender can time out after a remote system accepts the message. A real application needs a delivery contract and, where appropriate, an idempotency mechanism. A mock cannot settle that external question.
Where should a name be patched?
Patch the name that the code under test looks up. If a module imports a function into its own namespace, replacing the original module's function later may not replace that already-bound local name. Trace the import and the actual lookup rather than changing paths until a test happens to pass.
A simple interview explanation can name two modules: the module defining a function and the module using an imported binding. The patch target follows the latter lookup when that is where the call is made.
What do call assertions prove?
They show how the unit interacted with the fake dependency. They do not prove an email arrived, a database transaction committed or a remote API accepted the request. Those are separate integration boundaries that need suitable tests.
Choose assertions that express the contract. Checking every private helper call can make a test fail after an internal refactor even when users receive the same correct result. On the other hand, a call count is important here because the retry limit is part of the behavior.
How can a mock hide a mistake?
A very permissive mock may accept a misspelled method or an argument shape that the real dependency rejects. A specification or autospecced mock can help when it matches a suitable real interface. It still cannot reproduce every real failure, timing constraint or data rule.
Keep a small integration check for the actual boundary when one is needed. Do not label a test using only mocks as a production persistence or delivery test.
A practical interview review checklist
- Name the behavior the unit owns.
- State exactly which collaborator is fake.
- Test a successful result and a relevant failure.
- Assert only interactions that matter to the contract.
- Explain what the test deliberately does not prove.
For your next exercise, remove retrying from the dispatcher and make it return the sender's exception unchanged. Rewrite the test expectations first. This checks whether you understand the contract, rather than only the mock API.
References and next practice
Browse interview topics · Practise a question in Interview Challenge · How to Answer Technical Interview Questions Out Loud