Как издеваться над импортом, (издеваться над AB)?
Модуль A включает импорт B в его верхней части.
Легко, просто смоделируйте библиотеку в sys.modules, прежде чем она будет импортирована:
if wrong_platform():
sys.modules['B'] = mock.MagicMock()
и затем, если только A
не полагаться на конкретные типы данных, возвращаемых из объектов B:
import A
должен просто работать.
Вы также можете издеваться import A.B
:
Это работает, даже если у вас есть подмодули, но вы захотите смоделировать каждый модуль. Скажем, у вас есть это:
from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from foo.baz import Blah, getBlah, boink
Чтобы смоделировать, просто сделайте ниже, прежде чем импортировать модуль, который содержит выше:
sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()
(Мой опыт: у меня была зависимость, которая работает на одной платформе, Windows, но не работала на Linux, где мы проводим наши ежедневные тесты. Поэтому мне нужно было смоделировать зависимость для наших тестов. К счастью, это был черный ящик, поэтому Мне не нужно было устанавливать много взаимодействия.)
Дразнящие побочные эффекты
Приложение: На самом деле мне нужно было смоделировать побочный эффект, который занял некоторое время. Поэтому мне нужен был метод объекта, чтобы поспать секунду. Это будет работать так:
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)
И затем выполнение кода занимает некоторое время, как настоящий метод.
Mock
не будет исправлять некоторые магические атрибуты (__%s__
), как__name__
.