Skip to content

no-test-method-grafting

Avoid assigning replacement implementations directly onto resolved methods in tests.

Why

Grafting a function onto a collaborator or mock hides the boundary's callable contract and bypasses the mock's call and await records. An injected fake makes behavior explicit; configuring an existing contract-aware mock preserves its observation API. Scoped patches also restore real objects reliably.

Fix

Inject a concrete fake or configure the existing autospecced mock method's return_value or side_effect. Preserve the real method's synchronous or asynchronous contract, including synchronous awaitable returns. Explain other intentional runtime interception with an exact-code local suppression.

Examples

Before — flagged A test replaces a mock's resolved collaborator method
tests/test_delivery.py
from unittest.mock import Mock
class Sender:
def send(self, text: str) -> None:
pass
def test_delivery():
sender = Mock(spec=Sender)
messages = []
def record(text: str) -> None:
messages.append(text)
sender.send = record
After — preferred Configure behavior through an existing mock method
tests/test_delivery.py
from unittest.mock import create_autospec
class Sender:
def send(self, text: str) -> None:
pass
def test_delivery():
sender = create_autospec(Sender, instance=True, spec_set=True)
messages = []
sender.send.side_effect = messages.append
sender.send("hello")
sender.send.assert_called_once_with("hello")