2011-12-20 20 views
28

Mam następującą strukturę:Jak wyśmiać funkcję zdefiniowaną w module pakietu?

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

wynikiem python test.py jest Bar.

Jak naśmiewać się z printBar, aby powrócić Foo, aby printFoo go wydrukować?

EDIT: Bez modyfikacji jakiegokolwiek innego pliku, który test.py

Odpowiedz

16

Zgaduję masz zamiar drwić funkcję returnBar, chcesz używać 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

Wystarczy zaimportować moduł bar przed modułem foo i wyśmiewać go:

from mock import Mock 

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

from foo import printFoo 

printFoo() 

Podczas importowania returnBar w foo.py, jesteś wiązanie wartość modułu do zmiennej o nazwie returnBar. Ta zmienna jest lokalna, dlatego jest umieszczana w zamknięciu funkcji printFoo() po zaimportowaniu foo - a wartości w zamknięciu nie można zaktualizować za pomocą kodu z poza nią. Powinna więc mieć nową wartość (tj. Funkcję przedrzeźniania) przed zaimportowaniem importowania .

EDIT: poprzednie rozwiązanie działa, ale nie jest wydajne, ponieważ zależy od zamówienia importu. To nie jest zbyt idealne. Innym rozwiązaniem (czyli nastąpiło mi po pierwszym) jest import moduł bar w foo.py zamiast tylko importować returnBar() funkcję:

from dirBar import bar 

def printFoo(): 
    print bar.returnBar() 

będzie działać, ponieważ returnBar() teraz pobierać bezpośrednio z modułu zamiast bar zamknięcie. Więc jeśli zaktualizuję moduł, nowa funkcja zostanie odzyskana.

+0

Tak, problem był - miałem taki kod i nie chciałem ich zmieniać. Po dyskusji na freenode # python zdecydowałem się na refaktoryzację drugiego pliku (tutaj foo.py), więc będzie lepiej i czystszy – zalun

+0

@zalun czy istnieje link do tej dyskusji? Ciekawi mnie to! – brandizzi

+0

Nie mam pojęcia - właśnie stwierdziłem, że nie rejestruję niczego ... – zalun

-3

Innym sposobem radzenia sobie z tymi przypadku jest użycie jakiegoś iniekcji zależność.

Łatwym sposobem, aby to zrobić w Pythonie jest użycie magicznego **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) 

doprowadzi to do bardziej sprawdzalne kod (i zwiększyć modułowość/możliwość ponownego użycia).

+2

cały pomysł polega na tym, aby niczego nie modyfikować, z wyjątkiem test.py – zalun

Powiązane problemy