Ich habe eine Funktion (foo
), die eine andere Funktion aufruft (bar
). Wenn das Aufrufen von bar()
ein HttpError
auslöst, möchte ich es speziell behandeln, wenn der Statuscode 404 ist, andernfalls erneut auslösen.
Ich versuche, einige Unit-Tests für diese foo
-Funktion zu schreiben, wobei ich den Aufruf von bar()
verspotte. Leider kann ich den verspotteten Aufruf von bar()
nicht erhalten, um eine Exception auszulösen, die von meinem except
-Block abgefangen wird.
Hier ist mein Code, der mein Problem veranschaulicht:
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()
Ich folgte den Mock-Dokumenten , die besagen, dass Sie den side_effect
Einer Mock
-Instanz auf einen Exception
class, damit die verspottete Funktion den Fehler auslöst.
Ich habe mir auch einige andere verwandte Fragen und Antworten zu StackOverflow angesehen, und es sieht so aus, als ob ich das gleiche tue, was sie tun, um zu bewirken, dass Exception von ihrem Mock ausgelöst wird.
Warum führt das Setzen von side_effect
Von barMock
nicht dazu, dass das erwartete Exception
ausgelöst wird? Wie gehe ich vor, wenn ich etwas Seltsames tue, um die Logik in meinem except
-Block zu testen?
Ihr Mock löst die Ausnahme ganz gut aus, aber der Wert error.resp.status
Fehlt. Anstatt return_value
Zu verwenden, sagen Sie einfach Mock
, dass status
ein Attribut ist:
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
Zusätzliche Schlüsselwortargumente für Mock()
werden als Attribute für das resultierende Objekt festgelegt.
Ich habe Ihre Definitionen für foo
und bar
in ein Modul my_tests
Eingefügt, das in der Klasse HttpError
hinzugefügt wurde, damit ich es auch verwenden kann und Ihr Test kann dann zum Erfolg geführt werden:
>>> from my_tests import foo, HttpError
>>> import mock
>>> with mock.patch('my_tests.bar') as barMock:
... barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
... result = my_test.foo()
...
404 -
>>> result is None
True
Sie können sogar die Zeile print '404 - %s' % error.message
Sehen, aber ich glaube, Sie wollten stattdessen error.content
Verwenden. das ist jedenfalls das Attribut HttpError()
, das aus dem zweiten Argument gesetzt wird.