Tengo una función ( foo) que llama a otra función ( bar). Si la invocación bar()genera un HttpError, quiero manejarlo especialmente si el código de estado es 404; de lo contrario, vuelva a aumentar.
Estoy tratando de escribir algunas pruebas unitarias en torno a esta foofunción, burlándome de la llamada a bar(). Desafortunadamente, no puedo obtener la llamada simulada bar()para generar una excepción que es detectada por mi exceptbloqueo.
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()
Seguí los documentos de Mock que dicen que debe establecer el side_effectde una Mockinstancia en una Exceptionclase para que la función simulada genere el error.
También miré algunas otras preguntas y respuestas de StackOverflow relacionadas, y parece que estoy haciendo lo mismo que ellos están haciendo para causar una Excepción que se plantee por su simulacro.
- https://stackoverflow.com/a/10310532/346561
- Cómo usar Python Mock para generar una excepción, pero con Errno establecido en un valor dado
¿Por qué establecer el side_effectde barMockno causa que se aumente lo esperado Exception? Si estoy haciendo algo extraño, ¿cómo debo probar la lógica en mi exceptbloque?
fuente

resp.statuscódigo de allí. De dondeHTTPErrorvieneHttpErrores una clase definida en el de Googleapiclientlib que utilizamos en GAE. Está__init__definido con los parámetros,(resp, content)por lo que estaba intentando crear una instancia simulada para la respuesta, con el código de estado apropiado especificado.return_valueentonces;respno está siendo llamado .HttpErrory en su lugar intenté usar solo unaExceptioninstancia normal . Esto funciona perfectamente. Esto significa que debe tener algo que ver con cómo estoy configurando laHttpErrorinstancia, probablemente relacionado con cómo estoy creando unaMockinstancia para la respuesta.Respuestas:
Su simulacro está generando la excepción muy bien, pero
error.resp.statusfalta el valor. En lugar de usarreturn_value, solo digaMockquestatuses un atributo:Los argumentos de palabras clave adicionales
Mock()se establecen como atributos en el objeto resultante.Puse sus definiciones
fooybaren unmy_testsmódulo, agregado en laHttpErrorclase para que yo también pudiera usarlo, y su prueba se puede ejecutar con éxito:Incluso puedes ver la
print '404 - %s' % error.messagelínea correr, pero creo que querías usarlaerror.contentallí; ese es elHttpError()conjunto de atributos del segundo argumento, en cualquier caso.fuente
side_effectes la parte clave