Simulacro de una función para elevar una excepción para probar un bloque de excepción

Tengo una función ( foo ) que llama a otra función ( bar ). Si la invocación de la bar() genera un HttpError , quiero manejarlo especialmente si el código de estado es 404, de lo contrario volverá a subir.

Estoy tratando de escribir algunas pruebas unitarias en torno a esta función foo , burlándose de la llamada a la bar() . Desafortunadamente, no puedo obtener la llamada simulada a la bar() para generar una Excepción que es capturada 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() 

Seguí los documentos side_effect que dicen que debes establecer el efecto side_effect de una instancia Mock en una clase de Exception para que la función Mock side_effect el error.

También miré otras preguntas y respuestas relacionadas de StackOverflow, y parece que estoy haciendo lo mismo que ellos están haciendo para provocar que Exception se genere en 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 determinado

¿Por qué la configuración del side_effect de side_effect de barMock no hace que se barMock la Exception esperada? Si estoy haciendo algo raro, ¿cómo debo hacer para probar la lógica en mi bloque de except ?

Su simulacro está elevando la excepción muy bien, pero error.resp.status valor error.resp.status . En lugar de usar return_value , solo dile a Mock que el status es un atributo:

 barMock.side_effect = HttpError(mock.Mock(status=404), 'not found') 

Los argumentos de palabras clave adicionales para Mock() se establecen como atributos en el objeto resultante.

Puse sus definiciones de foo y bar en un módulo my_tests , agregado en la clase HttpError para que yo también pudiera usarlo, y luego su prueba puede ejecutarse 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 puede ver la línea de print '404 - %s' % error.message ejecutada, pero creo que quería usar error.content allí; ese es el atributo que HttpError() establece desde el segundo argumento, en cualquier caso.