Pregunta

Quiero simular MyApp que importa un módulo (ResourceX) que requiere un recurso que no está disponible en ese momento y no funcionará.

Una solución para esto es crear e importar un módulo simulado de ResourceX (denominado ResourceXSimulated) y desviarlo a MyApp como ResourceX. Quiero hacer esto para evitar romper mucho código y obtener todo tipo de excepciones de MyApp.

Estoy usando Python y debería ser algo como:

" Importar ResourceXSimulado como ResourceX "

" ResourceX.getData () " ;, en realidad llama a ResourceXSimultated.getData ()

Esperamos saber si Python admite este tipo de redirección.

Saludos.

INFORMACIÓN ADICIONAL: Tengo acceso a los archivos de origen.

ACTUALIZACIÓN: Estoy pensando en agregar el menor código posible a MyApp con respecto al uso del módulo falso y agregar este código cerca de las declaraciones de importación.

¿Fue útil?

Solución

Simplemente cambie todas las líneas import ResourceX en MyApp a import ResourceXSimulated como ResourceX , y líneas como desde ResourceX import Y a desde ResourceXSimulated import Y .

Sin embargo, si no tiene acceso a la fuente MyApp o hay otras razones para no cambiarlo, puede colocar su módulo en sys.modules antes de MyApp se carga solo:

import ResourceXSimulated
sys.modules['ResourceX'] = ResourceXSimulated

Nota: si ResourceX es un paquete, puede requerir más esfuerzo.

Otros consejos

Esto se llama parche de mono, y es una técnica bastante utilizada en lenguajes dinámicos como Python.

Entonces presumiblemente tienes una clase:

class MyOriginal(object):

    def method_x(self):
        do_something_expensive_you_dont_want_in_testing()


obj = MyOriginal()
obj.method_x()

así que en las pruebas quieres hacer otra cosa en lugar de method_x , pero debe ser transparente. Entonces, solo aproveche el lenguaje dinámico de Python:

def new_method_x(self):
    pretend_were_doing_something_expensive()

test_obj = MyOriginal()
test_obj.method_x = new_method_x # here's the monkeypatch
test_obj_method_x() # calls the new method

Es posible con el hack sys.modules , como ya se dijo.

Tenga en cuenta que si tiene control sobre el módulo ResourceX , ciertamente es mejor que lo cuide por sí mismo. Este es en realidad un patrón común cuando se escriben módulos que funcionan mejor cuando hay algún recurso presente, por ejemplo:

# foo.py
'''A module that provides interface to foo. 

Falls back to a dummy interface if foo is not available.
'''

try:
    from _foo import *
except ImportError:
    from _foo_dummy import *

A veces las personas lo hacen de una manera más orientada a objetos:

# foo.py
'''A module that provides interface to foo if it exists or to a dummy interface. 

Provides:
    frobnicate()   self-explanatory
    ...
'''

class DummyFoo:
    def frobnicate(self):
        pass
    ...

class UnixFoo(DummyFoo):
    def frobnicate(self):
        a_posix_call()
    ...

class GenericFoo(DummyFoo):
    def frobnicate(self):
        do_something_complicated()
    ...

# Create a default instance.
try:
   if (system == UNIX)
       instance = UnixFoo(system)
   else:
       instance = GenericFoo()
except Exception:
    instance = DummyFoo()

# Now export the public interface.
frobnicate = instance.frobnicate

Sí, es posible. Algunos entrantes:

Puede " desviar " módulos manipulando sys.modules. Mantiene una lista de módulos importados, y allí puede hacer que su módulo aparezca con el mismo nombre que el original. Sin embargo, debe hacer esta manipulación antes de cualquier módulo que importe el módulo que desea falsificar.

También puede hacer un paquete llamado con un nombre diferente, pero en ese paquete realmente use el nombre del módulo original, para su módulo completamente diferente. Esto funciona bien siempre que el módulo original no esté instalado.

En ninguno de estos casos puede usar ambos módulos al mismo tiempo. Para eso necesita parchear el módulo original.

Y, por supuesto: es perfectamente posible simplemente llamar al nuevo módulo con el nombre anterior. Pero puede ser confuso.

Sí, Python puede hacer eso, y siempre que los métodos expuestos en el módulo ResourceXSimulated '' vean y huelan '' como estos del módulo original, la aplicación no debería ver mucha diferencia (aparte de, supongo, rellenos de datos falsos, diferentes tiempos de respuesta y demás).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top