Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock patching from/import statement in Python

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

like image 250
oneself Avatar asked Jul 05 '12 19:07

oneself


People also ask

Can you mock an import in Python?

Rather than hacking on top of Python's import machinery, you can simply add the mocked module into sys. path , and have Python prefer it over the original module. Now, when the test suite is run, the mocked-lib subdirectory is prepended into sys. path and import A uses B from mocked-lib .

What does mock patch do Python?

mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.

What is the difference between mock and patch?

Mock is a type, and patch is a context. So you are going to pass or receive Mock instances as parameters, and apply patch contexts to blocks of code. (Lowercase 'mock' is just the name of the package.) Tests and test classes are often decorated with calls to patch.

Is there a way to mock imports in Python?

5 I found fine way to mock the imports in Python. It's Eric's Zaadisolution found herewhich I just use inside my Djangoapplication. I've got class SeatInterfacewhich is interface to Seatmodel class.

How to assign a mock () method to a python function?

Or you can just assign a Mock()directly: test.py: import sys sys.modules['B'] = Mock() import A Share Improve this answer

How to mock an import into a module?

20 How to mock an import, (mock A.B)? Module A includes import B at its top. Easy, just mock the library in sys.modules before it gets imported: if wrong_platform(): sys.modules['B'] = mock.MagicMock() and then, so long as Adoesn't rely on specific types of data being returned from B's objects: import A should just work.

Where do we patch an object in Python?

We must note that, we patch only where an object is looked up, which is not necessarily the same place as where it is defined. For example, consider following project structure that we want to test: Now, we want to test a_func but we want to mock out AClass using patch ().


2 Answers

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).

like image 182
Adam Wagner Avatar answered Sep 20 '22 07:09

Adam Wagner


patch works by patching names. You can't achieve anything by patching the name collections.defaultdict if you are using the name defaultdict (in the local namespace) to access the object. See the documentation at https://docs.python.org/3/library/unittest.mock.html#where-to-patch

like image 44
BrenBarn Avatar answered Sep 21 '22 07:09

BrenBarn