python – How to mock an import

python – How to mock an import

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

test.py:

import sys
sys.modules[B] = __import__(mock_B)
import A

print(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 Bs actual functions/variables/etc. Or you can just assign a Mock() directly:

test.py:

import sys
sys.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 module
b_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 B

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

python – How to mock an import

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 doesnt rely on specific types of data being returned from Bs objects:

import A

should just work.

You can also mock import A.B:

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

from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from 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 didnt 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 didnt 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 objects 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 sleep

def sleep_one(*args): 
    sleep(1)

# this gives us the mock objects that will be used
from 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.

Leave a Reply

Your email address will not be published. Required fields are marked *