El módulo A
incluye import B
en su parte superior. Sin embargo, bajo condiciones de prueba que me gustaría burlarse B
de A
(simulacro A.B
) y abstenerse completamente de la importación B
.
De hecho, B
no está instalado en el entorno de prueba a propósito.
A
es la unidad bajo prueba Tengo que importar A
con toda su funcionalidad. B
es el módulo que necesito burlarme. Pero ¿cómo puedo burlarse B
dentro A
y parada A
de la importación de los bienes B
, si lo primero que A
hace es la importación B
?
(La razón por la que B no está instalado es porque uso pypy para realizar pruebas rápidas y desafortunadamente B todavía no es compatible con pypy).
¿Como se puede hacer esto?
fuente
Mock
no parcheará algunos atributos mágicos (__%s__
) como__name__
.sys.modules['B'] = None
pero no parece funcionar.mock
y luego llamarmock.Mock()
El builtin
__import__
se puede burlar con la biblioteca 'simulacro' para un mayor control:Decir
A
parece:A.a()
devolucionesb_mock.func()
que se pueden burlar también.Nota para Python 3: como se indica en el registro de cambios para 3.0 ,
__builtin__
ahora se llamabuiltins
:El código en esta respuesta funciona bien si lo reemplaza
__builtin__
porbuiltins
Python 3.fuente
import_mock
me llamen porimport A
, pero no por nada que importe.ImportError: No module named '__builtin__'
__builtin__
__builtin__
porbuiltins
python3 ( docs.python.org/3/whatsnew/3.0.html?highlight=__builtin__ )Fácil, simplemente simula la biblioteca en sys.modules antes de que se importe:
y luego, siempre y cuando
A
no se base en tipos específicos de datos devueltos por los objetos de B: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:
Para burlarse, simplemente haga lo siguiente antes de importar el módulo que contiene lo anterior:
(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í:
Y luego el código tarda un tiempo en ejecutarse, al igual que el método real.
fuente
Me doy cuenta de que llego un poco tarde a la fiesta aquí, pero aquí hay una forma algo loca de automatizar esto con la
mock
biblioteca:(aquí hay un ejemplo de uso)
La razón por la que esto es tan ridículamente complicado es cuando se produce una importación, Python básicamente hace esto (por ejemplo
from herp.derp import foo
)sys.modules['herp']
? De lo contrario importalo. Si aun noImportError
sys.modules['herp.derp']
? De lo contrario importalo. Si aun noImportError
foo
desys.modules['herp.derp']
. MásImportError
foo = sys.modules['herp.derp'].foo
Hay algunas desventajas en esta solución pirateada: si algo más se basa en otras cosas en la ruta del módulo, este tipo de problemas lo arruina. Además, esto solo funciona para cosas que se importan en línea, como
o
fuente
La respuesta de Aaron Hall funciona para mí. Solo quiero mencionar una cosa importante,
si en
A.py
ti lo hacesfrom B.C.D import E
entonces en
test.py
debe burlarse de cada módulo a lo largo del camino, de lo contrario obtendráImportError
fuente
Encontré una buena manera de burlarse de las importaciones en Python. Aquí se encuentra la solución Zaadi de Eric que acabo de usar dentro de mi aplicación Django .
Tengo una clase
SeatInterface
que es la interfaz para laSeat
clase de modelo. Entonces dentro de miseat_interface
módulo tengo una importación de este tipo:Quería crear pruebas aisladas para la
SeatInterface
clase conSeat
clase burlada comoFakeSeat
. El problema era: cómo ejecutar las pruebas fuera de línea, donde la aplicación Django está inactiva. Tuve el siguiente error:La solución fue:
Y luego la prueba funciona mágicamente OK :)
fuente
Si haces un
import ModuleB
, realmente estás llamando al método incorporado__import__
como:Puede sobrescribir este método importando el
__builtin__
módulo y hacer un contenedor alrededor del__builtin__.__import__
método. O podrías jugar con elNullImporter
gancho delimp
módulo. Capturando la excepción y burlándose de su módulo / clase en elexcept
bloque.Puntero a los documentos relevantes:
docs.python.org:
__import__
Acceso a las partes internas de importación con el módulo imp
Espero que esto ayude. Se le recomienda encarecidamente que entre en los perímetros más arcanos de la programación de Python y que a) comprenda de manera sólida lo que realmente quiere lograr yb) comprenda a fondo las implicaciones es importante.
fuente