Andy McKay

May 09, 2015

Preventing typos with Python mock


Python mock is pretty cool, but there's been a recurring problem for me with mock in that if you access any property on a Mock it returns a method which is truthy. This means simple typos can exist in your testing.

As an example, in this library, there's a method from_nonce. If you just mock the object, then you can typo the method and it continues like normal:

>>> with mock.patch('braintree.CreditCard') as mocked:
...   assert mocked.from_none
...

This has happened to me and I didn't notice when I'd typo'd a mock call, like is_called. The test were wrong, but passed quite happily.

The better way is to pass the object to the Mock call as spec. Then only methods on the object can be called, for example:

>>> with mock.patch('braintree.CreditCard', spec=braintree.CreditCard) as mocked:
...   assert mocked.from_none
...
Traceback (most recent call last):
  [..snip]
  File "/Users/andy/.virtualenvs/solitude/lib/python2.7/site-packages/mock.py", line 658, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'from_none'

Much better.

Update: Paul Winkler points out that instead of passing spec=braintree.CreditCard through you can pass autospec=True. Good call.