2011-12-20 4 views
28

У меня следующую структуру:Как высмеять функцию, определенную в модуле пакета?

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

результат python test.py - Bar.

Как насмехаться с printBar, чтобы вернуть его Foo, чтобы printFoo распечатал его?

EDIT: Без изменения любого другого файла, который test.py

ответ

16

Я предполагаю, что вы собираетесь дразнить функцию returnBar, вы хотели бы использовать 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

Просто импортировать bar модуль до foo модуля и издевается его:

from mock import Mock 

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

from foo import printFoo 

printFoo() 

Когда вы импортируете returnBar в foo.py, вы привязку значение модуля к переменной, называемой returnBar. Эта переменная является локальной, поэтому помещается в закрытие функции printFoo(), когда импортируется foo - и значения в закрытии не могут быть обновлены кодом из него. Таким образом, он должен иметь новое значение (то есть, насмешку) до импорт foo.

EDIT: предыдущее решение работает, но не является надежным, поскольку оно зависит от порядка импорта. Это не очень хорошо. Другое решение (что произошло со мной после первого) является импортировать bar модуль в foo.py вместо только импортировать returnBar() функцию:

from dirBar import bar 

def printFoo(): 
    print bar.returnBar() 

Это будет работать, потому что returnBar() теперь извлекается непосредственно из bar модуля вместо закрытие. Поэтому, если я обновляю модуль, будет восстановлена ​​новая функция.

+0

Да, проблема была: у меня был такой код, и я не хотел их менять. После обсуждения freenode # python я решил реорганизовать другой файл (здесь foo.py), так что будет лучше и чище – zalun

+0

@zalun есть ссылка на это обсуждение? Мне это интересно! – brandizzi

+0

не знаю - я только что нашел, что ничего не регистрирую ... – zalun

-3

Другой способ иметь дело с теми, кто случае использовать некоторые инъекции зависимостей.

простой способ сделать это в Python, чтобы использовать волшебный **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) 

это приведет к более проверяемым кода (и увеличить модульность/повторное использование).

+2

вся идея состоит в том, чтобы ничего не изменять, кроме test.py – zalun

4

Лучшее место, которое я нашел, чтобы решить издевательские вопросы, является: http://alexmarandon.com/articles/python_mock_gotchas/

Вы должны издеваться функцией модуля импортируемого класса при тестировании.

+3

Ссылка на ответы не рекомендуется, почему вы не суммируете, что описано на странице здесь? – user22866

Смежные вопросы