J'ai une fonction ( foo
) qui appelle une autre fonction ( bar
). Si l'invocation bar()
déclenche un HttpError
, je veux le gérer spécialement si le code d'état est 404, sinon re-relancer.
J'essaie d'écrire des tests unitaires autour de cette foo
fonction, en se moquant de l'appel à bar()
. Malheureusement, je ne peux pas obtenir l'appel simulé à bar()
pour lever une exception qui est interceptée par mon except
bloc.
Voici mon code qui illustre mon problème:
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()
J'ai suivi les documents Mock qui disent que vous devez définir le side_effect
d'une Mock
instance sur une Exception
classe pour que la fonction simulée lève l'erreur.
J'ai également regardé d'autres questions et réponses liées à StackOverflow, et il semble que je fais la même chose qu'ils font pour provoquer et déclencher une exception par leur simulation.
- https://stackoverflow.com/a/10310532/346561
- Comment utiliser Python Mock pour lever une exception - mais avec Errno défini sur une valeur donnée
Pourquoi le réglage side_effect
de barMock
ne provoque-t-il pas le relèvement de l'attendu Exception
? Si je fais quelque chose de bizarre, comment dois-je procéder pour tester la logique de mon except
bloc?
la source
resp.status
code ici. D'oùHTTPError
vient-il?HttpError
est une classe définie dans Googleapiclient
lib que nous utilisons dans GAE. Il__init__
est défini avec les paramètres,(resp, content)
donc j'essayais de créer une instance fictive pour la réponse, avec le code d'état approprié spécifié.return_value
alors;resp
n'est pas appelé .HttpError
et j'ai essayé d'utiliser à la place uneException
instance régulière . Cela fonctionne parfaitement. Cela signifie qu'il doit avoir quelque chose à voir avec la façon dont je configure l'HttpError
instance, probablement lié à la façon dont je crée uneMock
instance pour la réponse.Réponses:
Votre simulation soulève très bien l'exception, mais la
error.resp.status
valeur est manquante. Plutôt que d'utiliserreturn_value
, dites simplementMock
questatus
c'est un attribut:Les arguments de mot-clé supplémentaires à
Mock()
sont définis comme attributs sur l'objet résultant.J'ai mis vos définitions
foo
etbar
dans unmy_tests
module, ajouté dans laHttpError
classe pour que je puisse l'utiliser aussi, et votre test peut ensuite être exécuté avec succès:Vous pouvez même voir la
print '404 - %s' % error.message
ligne courir, mais je pense que vous vouliez l'utiliser à laerror.content
place; c'est en tout cas lesHttpError()
ensembles d' attributs du deuxième argument.la source
side_effect
est la partie clé