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 B
s 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__
tobuiltins
(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.