Eu tenho uma função ( foo
) que chama outra função ( bar
). Se a invocação bar()
gerar um HttpError
, quero lidar com isso especialmente se o código de status for 404, caso contrário, aumente novamente.
Estou tentando escrever alguns testes de unidade em torno dessa foo
função, zombando da chamada para bar()
. Infelizmente, não consigo fazer a chamada simulada bar()
para gerar uma exceção que é capturada pelo meu except
bloco.
Aqui está meu código que ilustra meu 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()
Eu segui os documentos Mock que dizem que você deve definir o side_effect
de uma Mock
instância para uma Exception
classe para que a função simulada eleve o erro.
Eu também olhei algumas outras perguntas e respostas relacionadas ao StackOverflow e parece que estou fazendo a mesma coisa que eles estão fazendo para causar e Exception ser gerado por seu mock.
- https://stackoverflow.com/a/10310532/346561
- Como usar o Python Mock para levantar uma exceção - mas com Errno definido para um determinado valor
Por que configurar o side_effect
de barMock
não causar o Exception
aumento do esperado ? Se estou fazendo algo estranho, como devo proceder para testar a lógica no meu except
bloco?
fonte
resp.status
código lá. De ondeHTTPError
vem?HttpError
é uma classe definida na biblioteca do Googleapiclient
que usamos no GAE. Ele__init__
é definido com os parâmetros,(resp, content)
então eu estava tentando criar uma instância simulada para a resposta, com o código de status apropriado especificado.return_value
;resp
não está sendo chamado .HttpError
e, em vez disso, tentei usar apenas umaException
instância normal . Isso funciona perfeitamente. Isso significa que deve ter algo a ver com como estou configurando aHttpError
instância, provavelmente relacionado a como estou criando umaMock
instância para a resposta.Respostas:
Seu mock está levantando a exceção muito bem, mas o
error.resp.status
valor está faltando. Em vez de usarreturn_value
, basta dizerMock
questatus
é um atributo:Argumentos de palavra-chave adicionais para
Mock()
são definidos como atributos no objeto resultante.Eu coloquei suas definições
foo
ebar
em ummy_tests
módulo, adicionei naHttpError
classe para que eu pudesse usá-lo também, e seu teste pode ser executado com sucesso:Você pode até ver a
print '404 - %s' % error.message
linha rodando, mas acho que você queria usarerror.content
lá; esses são osHttpError()
conjuntos de atributos do segundo argumento, de qualquer maneira.fonte
side_effect
é a parte principal