web-dev-qa-db-fra.com

Comment se moquer d'une fonction définie dans un module d'un package?

J'ai une structure suivante:

|-- 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()

le résultat de python test.py est Bar.

Comment se moquer du printBar pour qu'il retourne Foo afin que printFoo l'imprime?

EDIT: sans modifier aucun autre fichier qui test.py

42
zalun

Je suppose que vous allez vous moquer de la fonction returnBar, vous souhaitez utiliser patch décorateur :

from mock import patch

from foo import printFoo

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

test_printFoo()
35
number5

Importez simplement le module bar avant le module foo et moquez-le:

from mock import Mock

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

from foo import printFoo

printFoo()

Lorsque vous importez le returnBar dans foo.py, Vous liez la valeur du module à une variable appelée returnBar. Cette variable est locale, elle est donc placée dans la fermeture de la fonction printFoo() lorsque foo est importée - et les valeurs dans la fermeture ne peuvent pas être mises à jour par du code extérieur. Ainsi, il devrait avoir la nouvelle valeur (c'est-à-dire la fonction moqueuse) avant l'importation de foo.

EDIT : la solution précédente fonctionne mais n'est pas robuste car elle dépend de l'ordre des importations. Ce n'est pas vraiment l'idéal. Une autre solution (qui m'est apparue après la première) consiste à importer le module bar dans foo.py Au lieu d'importer uniquement la fonction returnBar():

from dirBar import bar

def printFoo():
    print bar.returnBar()

Cela fonctionnera car la returnBar() est maintenant récupérée directement à partir du module bar au lieu de la fermeture. Donc, si je mets à jour le module, la nouvelle fonction sera récupérée.

26
brandizzi