Mam funkcję ( foo
), która wywołuje inną funkcję ( bar
). Jeśli wywołanie bar()
wywołuje podniesienie HttpError
, chcę to obsłużyć specjalnie, jeśli kod statusu to 404, w przeciwnym razie ponownie podniesie.
Próbuję napisać kilka testów jednostkowych wokół tej foo
funkcji, wyszydzając wywołanie bar()
. Niestety, nie mogę uzyskać wyśmiewanego wezwania bar()
do podniesienia wyjątku, który został przechwycony przez mój except
blok.
Oto mój kod, który ilustruje mój problem:
import unittest
import mock
from apiclient.errors import HttpError
class FooTests(unittest.TestCase):
@mock.patch('my_tests.bar')
def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock):
barMock.return_value = True
result = foo()
self.assertTrue(result) # passes
@mock.patch('my_tests.bar')
def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock):
barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found')
result = foo()
self.assertIsNone(result) # fails, test raises HttpError
@mock.patch('my_tests.bar')
def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock):
barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error')
with self.assertRaises(HttpError): # passes
foo()
def foo():
try:
result = bar()
return result
except HttpError as error:
if error.resp.status == 404:
print '404 - %s' % error.message
return None
raise
def bar():
raise NotImplementedError()
I po Mock dokumenty , które mówią, że należy ustawić side_effect
z Mock
instancji do Exception
klasy mają szydzili funkcja podniesienia błąd.
Przyjrzałem się również innym powiązanym pytaniom i odpowiedziom dotyczącym StackOverflow i wygląda na to, że robię to samo, co oni, aby wywołać wyjątek przez ich próbę.
- https://stackoverflow.com/a/10310532/346561
- Jak używać Python Mock do zgłaszania wyjątku - ale z Errno ustawionym na podaną wartość
Dlaczego jest ustawienie side_effect
od barMock
nie powodując oczekiwany Exception
zostać podniesiona? Jeśli robię coś dziwnego, jak mam przetestować logikę w moim except
bloku?
źródło
resp.status
tam kod. Skąd sięHTTPError
bierze?HttpError
to klasa zdefiniowana w bibliotece Google,apiclient
której używamy w GAE. Jest__init__
zdefiniowany za pomocą parametrów,(resp, content)
więc próbowałem utworzyć próbną instancję dla odpowiedzi, z określonym odpowiednim kodem stanu.return_value
wtedy używać użytkownika ;resp
nie jest wezwany .HttpError
i zamiast tego spróbowałem użyć zwykłejException
instancji. To działa doskonale. Oznacza to, że musi to mieć coś wspólnego z konfiguracjąHttpError
instancji, prawdopodobnie związaną z tym, jak tworzęMock
instancję dla odpowiedzi.Odpowiedzi:
Twoja makieta podnosi wyjątek, ale
error.resp.status
brakuje wartości. Zamiast używaćreturn_value
, po prostu powiedz,Mock
żestatus
jest to atrybut:Dodatkowe argumenty słów kluczowych do
Mock()
są ustawiane jako atrybuty obiektu wynikowego.Umieściłem twoje
foo
ibar
definicje wmy_tests
module, dodanym naHttpError
zajęciach, więc mogę go również użyć, a twój test może zostać uruchomiony pomyślnie:Możesz nawet zobaczyć przebieg
print '404 - %s' % error.message
linii, ale myślę,error.content
że zamiast tego chciałeś użyć tego; w każdym razie to jestHttpError()
zestaw atrybutów z drugiego argumentu.źródło
side_effect
jest kluczowa część