Jak przetestować następujący kod za pomocą próbnych (używając próbnych, dekoratora łatek i wartowników dostarczonych przez frameworka Michaela Foorda ):
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
python
mocking
with-statement
Daryl Spitzer
źródło
źródło
Odpowiedzi:
Sposób na dokonanie tego zmienił się w pozornej wersji 0.7.0, która wreszcie obsługuje wyśmiewanie metod protokołu python (metody magiczne), szczególnie przy użyciu MagicMock:
http://www.voidspace.org.uk/python/mock/magicmock.html
Przykład wyśmiewania otwarty jako menedżer kontekstu (ze strony przykładów w dokumentacji próbnej):
źródło
__enter__
i__exit__
wyśmiewa również obiekty - czy to drugie podejście jest nieaktualne, czy nadal przydatne?file
nie ma!mock_open
jest częściąmock
frameworka i jest bardzo prosty w użyciu.patch
użyte jako kontekst zwraca obiekt użyty do zastąpienia załatanego: możesz go użyć, aby uprościć test.Python 3.x
Użyj
builtins
zamiast__builtin__
.Python 2.7
mock
nie jest częściąunittest
i powinieneś łatać__builtin__
Skrzynia dekoratora
Jeśli użyjesz
patch
jako dekoratora, używającmock_open()
wyniku jakonew
patch
argumentu, może to być trochę dziwne.W takim przypadku lepiej użyć
new_callable
patch
argumentu i pamiętać, że każdy dodatkowy argument,patch
który nie będzie używany, zostanie przekazany donew_callable
działania zgodnie z opisem wpatch
dokumentacji .Na przykład udekorowana wersja dla Python 3.x to:
Pamiętaj, że w tym przypadku
patch
doda obiekt próbny jako argument funkcji testowej.źródło
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
można przekonwertować na składnię dekoratora? Próbowałem, ale nie jestem pewien, na co muszę przejść@patch("builtins.open", ...)
jako drugi argument.return_value
ofmock_open
na inny próbny obiekt i potwierdzić drugie próbnereturn_value
), ale zadziałało, dodającmock_open
asnew_callable
.six
moduł, aby mieć spójnymock
moduł. Ale nie wiem, czy mapuje równieżbuiltins
we wspólnym module.Dzięki najnowszym wersjom mocka możesz użyć naprawdę przydatnego pomocnika mock_open :
źródło
.write
połączeń?handle.write.assert_any_call()
. Możesz także użyć,handle.write.call_args_list
aby odebrać każde połączenie, jeśli kolejność jest ważna.m.return_value.write.assert_called_once_with('some stuff')
jest lepsze imo. Unika rejestracji połączenia.Mock.call_args_list
jest bezpieczniejsze niż wywoływanie którejkolwiek zMock.assert_xxx
metod. Jeśli źle przeliterujesz którykolwiek z tych drugich, będąc atrybutami Mocka, zawsze będą cicho przechodzić.Aby użyć mock_open dla prostego pliku
read()
(oryginalny fragment mock_open już podany na tej stronie jest przeznaczony bardziej do zapisu):Uwaga, jak w dokumentacji dla mock_open, jest to specjalnie dla
read()
, więc nie będzie działać z typowymi wzorcami, takimi jakfor line in f
na przykład.Używa języka Python 2.6.6 / mock 1.0.1
źródło
for line in opened_file:
rodzajem kodu. Próbowałem eksperymentować z iterowalnym StringIO, które implementuje__iter__
i używa tego zamiastmy_text
, ale bez powodzenia.read()
więc nie będzie działać w twoimfor line in opened_file
przypadku; Zredagowałem post, aby wyjaśnićfor line in f:
można osiągnąć przez wyśmiewanie wartości zwracanejopen()
jako obiektu StringIO .with open("any_string") as f: print f.read()
Najlepsza odpowiedź jest przydatna, ale trochę ją rozwinąłem.
Jeśli chcesz ustawić wartość swojego obiektu pliku (
f
inas f
) na podstawie argumentów przekazanychopen()
tutaj, możesz to zrobić w następujący sposób:Zasadniczo
open()
zwróci obiekt iwith
wywoła__enter__()
ten obiekt.Aby poprawnie kpić, musimy kpić,
open()
aby zwrócić próbny obiekt. Ten próbny obiekt powinien następnie wyśmiewać__enter__()
wywołanie (MagicMock
zrobi to za nas), aby zwrócić próbny obiekt danych / pliku, który chcemy (stądmm.__enter__.return_value
). Wykonanie tego przy użyciu 2 próbnych sposobów w powyższy sposób pozwala nam uchwycić przekazane argumentyopen()
i przekazać je naszymdo_something_with_data
metodzie.Przekazałem cały próbny plik jako ciąg znaków
open()
ido_something_with_data
wyglądałem tak:To przekształca ciąg w listę, dzięki czemu możesz wykonać następujące czynności, tak jak w przypadku normalnego pliku:
źródło
__enter__
? To zdecydowanie bardziej przypomina hack niż zalecany sposób.Mogę być trochę spóźniony do gry, ale zadziałało to dla mnie, gdy zadzwoniłem
open
do innego modułu bez konieczności tworzenia nowego pliku.test.py
MyObj.py
Przez łatanie
open
funkcji w__builtin__
moim modulemock_open()
mogę wyśmiewać zapisywanie do pliku bez jego tworzenia.Uwaga: Jeśli korzystasz z modułu, który używa cytonu, lub twój program w jakikolwiek sposób zależy od cytonu, musisz zaimportować moduł cytonu, umieszczając
__builtin__
goimport __builtin__
na górze pliku. Jeśli__builtin__
używasz cytonu, nie będziesz mógł kpić z tego uniwersalnego .źródło
import __builtin__
do mojego modułu testowego. Ten artykuł pomógł wyjaśnić, dlaczego ta technika działa tak dobrze, jak ona: ichimonji10.name/blog/6Aby załatać wbudowaną funkcję open () z unittest:
Działa to w przypadku poprawki do odczytu konfiguracji json.
Wyśmiewanym obiektem jest obiekt io.TextIOWrapper zwrócony przez funkcję open ()
źródło
Jeśli nie potrzebujesz już żadnego pliku, możesz udekorować metodę testową:
źródło