2011-12-20 13 views
28

Tengo una estructura siguiente:Cómo simular una función definida en un módulo de un paquete?

|-- dirBar 
| |-- __init__.py 
| |-- bar.py 
|-- foo.py 
`-- test.py 

bar.py

def returnBar(): 
    return 'Bar' 

foo.py

from dirBar.bar import returnBar 

def printFoo(): 
    print returnBar() 

test.py

from mock import Mock 

from foo import printFoo 
from dirBar import bar 

bar.returnBar = Mock(return_value='Foo') 

printFoo() 

el resultado de python test.py es Bar.

¿Cómo burlarse del printBar para que vuelva Foo para que printFoo lo imprima?

EDIT: Sin modificar cualquier otro archivo que test.py

Respuesta

16

supongo que va a burlarse de la función returnBar, desea utilizar patch decorator:

from mock import patch 

from foo import printFoo 

@patch('foo.returnBar') 
def test_printFoo(mockBar): 
    mockBar.return_value = 'Foo' 
    printFoo() 

test_printFoo() 
23

Sólo tiene que importar el módulo bar antes de que el módulo de foo y se burlan de él:

from mock import Mock 

from dirBar import bar 
bar.returnBar = Mock(return_value='Foo') 

from foo import printFoo 

printFoo() 

Al importar el returnBar en foo.py, va a enlazar el valor del módulo a una variable llamada returnBar. Esta variable es local, por lo que se pone en el cierre de la función printFoo() cuando se importa foo, y los valores en el cierre no se pueden actualizar por código desde fuera de él. Por lo tanto, debe tener el nuevo valor (es decir, la función de burla) antes de la importación de foo.

EDIT: la solución anterior funciona pero no es robusta ya que depende de ordenar las importaciones. Eso no es muy ideal. Otra solución (que me ocurrió después de la primera) es importar el módulo de bar en foo.py en lugar de importación exclusivamente la función returnBar():

from dirBar import bar 

def printFoo(): 
    print bar.returnBar() 

Esto funciona porque el returnBar() ahora se recuperan directamente desde el módulo en lugar de bar el cierre. Entonces, si actualizo el módulo, se recuperará la nueva función.

+0

Sí, el problema era que tenía el código así y no quería cambiarlos. Después de una discusión sobre freenode # python he decidido refactorizar el otro archivo (aquí foo.py) así que será mejor y más limpio – zalun

+0

@zalun ¿hay algún enlace a esta discusión? ¡Tengo curiosidad por eso! – brandizzi

+0

no tengo idea - Acabo de descubrir que no inicie sesión ... – zalun

-3

Otra forma de hacer frente a los casos es utilizar alguna de inyección de dependencia.

Una forma sencilla de hacerlo en Python es el uso de la mágica **kwargs:

foo.py

from dirBar.bar import returnBar 

def printFoo(**kwargs): 
    real_returnBar = kwargs.get("returnBar", returnBar) 
    print real_returnBar() 

test.py

from mock import Mock 

from foo import printFoo 
from dirBar import bar 

mocked_returnBar = Mock(return_value='Foo') 

printFoo(returnBar=mocked_returnBar) 

esto conducirá a una mayor comprobable código (y aumentar la modularidad/reutilización).

+2

la idea es no modificar nada, excepto el test.py – zalun

4

El mejor lugar que he encontrado para resolver los problemas de burla es: http://alexmarandon.com/articles/python_mock_gotchas/

Usted debe burlarse de la función del módulo que está siendo importado por la clase debajo de la prueba.

+3

, se desalienta el enlace de las respuestas, ¿por qué no resume qué está documentado aquí? – user22866

Cuestiones relacionadas