¿Cómo burlarse de una importación (simulacro AB)?
El módulo A incluye la importación B en su parte superior.
Fácil, simplemente simula la biblioteca en sys.modules antes de que se importe:
if wrong_platform():
sys.modules['B'] = mock.MagicMock()
y luego, siempre y cuando A
no se base en tipos específicos de datos devueltos por los objetos de B:
import A
debería funcionar
También puedes burlarte de import A.B
:
Esto funciona incluso si tiene submódulos, pero querrá burlarse de cada módulo. Digamos que tienes esto:
from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from foo.baz import Blah, getBlah, boink
Para burlarse, simplemente haga lo siguiente antes de importar el módulo que contiene lo anterior:
sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()
(Mi experiencia: tenía una dependencia que funcionaba en una plataforma, Windows, pero no funcionaba en Linux, donde ejecutamos nuestras pruebas diarias. Así que necesitaba burlarme de la dependencia para nuestras pruebas. Por suerte era una caja negra, así que No necesitaba configurar mucha interacción).
Efectos secundarios burlones
Anexo: En realidad, necesitaba simular un efecto secundario que tomó algún tiempo. Así que necesitaba un método de objeto para dormir por un segundo. Eso funcionaría así:
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)
Y luego el código tarda un tiempo en ejecutarse, al igual que el método real.
Mock
no parcheará algunos atributos mágicos (__%s__
) como__name__
.