Watch out for Mock(spec)

Despite mocks being a bit of a smell, they are handy and I do find myself using them from time to time. As a cheap way to get some extra checks, I try to always make use of autospec=True in my mock.patch() calls.

Sometimes instead of patch I end up making Mock instances myself to attach to objects or pass into functions, and for those I had been using replacement = Mock(spec=original) and assuming that in addition to attribute access, function signatures were being checked. However, I recently discovered that this wasn't the case, and instead I should be using replacement = create_autospec(original) (docs):

>>> m1 = mock.Mock(spec=lambda: None)
>>> m2 = mock.create_autospec(spec=lambda: None)
>>> m1(1)
<Mock name='mock()' id='4377526960'>
>>> m2(1)
# snip
TypeError: too many positional arguments

(I initially thought this was a bug but Michael Foord put me straight.)

Comments !