How to mock an import How to mock an import python python

How to mock an import


You can assign to sys.modules['B'] before importing A to get what you want:

test.py:

import syssys.modules['B'] = __import__('mock_B')import Aprint(A.B.__name__)

A.py:

import B

Note B.py does not exist, but when running test.py no error is returned and print(A.B.__name__) prints mock_B. You still have to create a mock_B.py where you mock B's actual functions/variables/etc. Or you can just assign a Mock() directly:

test.py:

import syssys.modules['B'] = Mock()import A


The builtin __import__ can be mocked with the 'mock' library for more control:

# Store original __import__orig_import = __import__# This will be the B moduleb_mock = mock.Mock()def import_mock(name, *args):    if name == 'B':        return b_mock    return orig_import(name, *args)with mock.patch('__builtin__.__import__', side_effect=import_mock):    import A

Say A looks like:

import Bdef a():    return B.func()

A.a() returns b_mock.func() which can be mocked also.

b_mock.func.return_value = 'spam'A.a()  # returns 'spam'

Note for Python 3:As stated in the changelog for 3.0, __builtin__ is now named builtins:

Renamed module __builtin__ to builtins (removing the underscores, adding an ā€˜sā€™).

The code in this answer works fine if you replace __builtin__ by builtins for Python 3.


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 A doesn't rely on specific types of data being returned from B's objects:

import A

should just work.

You can also mock import A.B:

This works even if you have submodules, but you'll want to mock each module. Say you have this:

from foo import This, That, andTheOtherThingfrom foo.bar import Yada, YadaYadafrom foo.baz import Blah, getBlah, boink

To mock, simply do the below before the module that contains the above is imported:

sys.modules['foo'] = MagicMock()sys.modules['foo.bar'] = MagicMock()sys.modules['foo.baz'] = MagicMock()

(My experience: I had a dependency that works on one platform, Windows, but didn't work on Linux, where we run our daily tests.So I needed to mock the dependency for our tests. Luckily it was a black box, so I didn't need to set up a lot of interaction.)

Mocking Side Effects

Addendum: Actually, I needed to simulate a side-effect that took some time. So I needed an object's method to sleep for a second. That would work like this:

sys.modules['foo'] = MagicMock()sys.modules['foo.bar'] = MagicMock()sys.modules['foo.baz'] = MagicMock()# setup the side-effect:from time import sleepdef sleep_one(*args):     sleep(1)# this gives us the mock objects that will be usedfrom foo.bar import MyObject my_instance = MyObject()# mock the method!my_instance.method_that_takes_time = mock.MagicMock(side_effect=sleep_one)

And then the code takes some time to run, just like the real method.