An autospecced mock accepts the callable signature of the object it stands in for.
Python testing: autospec catches a changed call signature
Operation contract
The shipping operation has a required receipt ID and a keyword-only region. The mock records a valid call and rejects a positional region. A plain unconstrained Mock would accept that mistaken call and let a test pass even though the real function rejects it. The example also checks exact call arguments so a missing or swapped field is visible.
Failure and ownership boundary
Autospec does not test the real function’s business behavior or external effects. A test suite still needs contract cases against the real implementation. Computed attributes and descriptor side effects can complicate autospec inspection; use it where the inspected interface is stable. Python unittest.mock: inject a collaborator failure before publication and Python positional-only and keyword-only parameters: keep call roles explicit give the surrounding contract.
Working program
from unittest.mock import create_autospec
def submit_receipt(receipt_id, *, region):
return f"{region}:{receipt_id}"
submission = create_autospec(submit_receipt, return_value="queued")
print(submission(41, region="DEL"))
submission.assert_called_once_with(41, region="DEL")
try:
submission(41, "DEL")
except TypeError:
print("positional region rejected")
print("real function:", submit_receipt(41, region="DEL"))Output
queued
positional region rejected
real function: DEL:41Costs and limits
Autospec adds mock/signature bookkeeping to each test call; it is not a throughput stand-in for a real service. The interface check is fixed-size for this function, while the actual operation cost is outside the fixture.
Common Mistakes
- A signature-correct mock can still return an unrealistic result.
- An unconstrained Mock can accept arguments the real function rejects.
Connected lessons
Python unittest.mock: inject a collaborator failure before publication, Python positional-only and keyword-only parameters: keep call roles explicit, Python refactoring: preserve rejected inputs as well as accepted results.
