Burlarse de una función para elevar una excepción para probar un bloque excepto
Tengo una función (foo
) que llama a otra función (bar
). Si invocando bar()
se genera un HttpError
, quiero manejarlo especialmente si el código de estado es 404, de lo contrario se vuelve a generar.
Estoy tratando de escribir algunas pruebas unitarias alrededor de esta función foo
, burlándose de la llamada a bar()
. Desafortunadamente, no puedo obtener la llamada burlada a bar()
para levantar una Excepción que es atrapada por mi bloque except
.
Aquí está mi código que ilustra mi problema:
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 seguido de los Mock docs que dicen que debe establecer el side_effect
de una instancia Mock
a una clase Exception
para que la función burlada genere el error.
También miré algunas otras preguntas y respuestas relacionadas con StackOverflow, y parece que estoy haciendo lo mismo que están haciendo para causar que la Excepción sea planteada por su burla.
- https://stackoverflow.com/a/10310532/346561
- Cómo usar Python Mock para generar una excepción-pero con Errno establecido a un valor dado
¿Por qué establecer el side_effect
de barMock
no causa que se eleve el Exception
esperado? Si estoy haciendo algo raro, ¿cómo debería probar la lógica en mi bloque except
?
1 answers
Su mock está elevando la excepción muy bien, pero falta el valor error.resp.status
. En lugar de usar return_value
, simplemente diga Mock
que status
es un atributo:
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
Argumentos de palabra clave adicionales a Mock()
se establecen como atributos en el objeto resultante.
Pongo sus definiciones foo
y bar
en un módulo my_tests
, añadido en el HttpError
class así que podría usarlo también, y su prueba entonces se puede ejecutar con éxito:
>>> 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
Incluso puedes ver la línea print '404 - %s' % error.message
correr, pero yo piensa que querías usar error.content
allí en su lugar; ese es el atributo HttpError()
establece desde el segundo argumento, en cualquier caso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 19:50:58