Mock patching from/import statement in Python

oneself picture oneself · Jul 5, 2012 · Viewed 24.8k times · Source

I am trying to get mock.patch to work on the following piece of sample code:

from mock import patch
from collections import defaultdict

with patch('collections.defaultdict'):
  d = defaultdict()
  print 'd:', d

This outputs the following:

d: defaultdict(None, {})

Which means that defaultdict was not patched.

If I replace the from/import statement with a straight import statement it works:

from mock import patch
import collections

with patch('collections.defaultdict'):
 d = collections.defaultdict()
 print 'd:', d

Output is:

d: <MagicMock name='defaultdict()' id='139953944084176'>

Is there any way to patch a call using from/import?

Thank you

Answer

Adam Wagner picture Adam Wagner · Jul 5, 2012

If you're patching something in the same module, you can use __main__:

from mock import patch
from collections import defaultdict

with patch('__main__.defaultdict'):
    d = defaultdict()
    print 'd:', d

If you're mocking something for an imported module, however, you'll want to use that module's name so the correct reference (or name) is patched:

# foo.py

from collections import defaultdict

def bar():
    return defaultdict()


# foo_test.py    

from mock import patch
from foo import bar

with patch('foo.defaultdict'):
    print bar()

The point here is that patch wants the full path to the thing it is patching. This just looks a little weird when patching something in the current module, since folks don't often use __main__ (or have to refer to the current module, for that matter).