20 votes

Python PropertyMock effet secondaire avec AttributeError et ValueError

Je essaie de simuler une propriété d'une classe (@property decorator) et je suis tombé sur ce comportement incorrect:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=AttributeError)
 >>> m.p

Le comportement correct est le suivant:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=ValueError)
 >>> m.p
 Traceback (most recent call last)
 [...]
 ValueError

Je ne peux pas comprendre pourquoi le fait de définir une exception différente me donne des résultats différents. Le résultat attendu dans les deux cas est que l'exception devrait être levée! Donc, la ligne In[4] devrait lever un AttributeError. Ce n'est pas le cas.

Quelqu'un peut-il m'éclairer?

Addendum: La propriété que j'essaie de vérifier effectue une vérification intelligente pour voir si la valeur passée est sensée. Si ladite valeur n'est pas sensée, elle renvoie AttributeError car je comprends que c'est l'exception correcte en Python. Ainsi, je dois vérifier le code qui utilise la propriété pour l'échec ainsi que pour le succès. Ainsi, en utilisant un MagicMock pour simuler la propriété et lever ladite exception. Un exemple trivial serait:

@x.setter
def x(self, value):
    if value < 0:
         raise AttributeError("La valeur ne peut pas être négative!")
    self._x = value

21voto

Max Tepkeev Points 2486

Je sais que cette question est ancienne, mais je viens juste d'avoir le même problème et j'ai trouvé cette question. De plus, le signalement de bug soumis il y a presque deux ans n'a pas semblé attirer l'attention, donc je pensais partager la solution que j'ai trouvée au cas où quelqu'un d'autre aurait ce problème.

Donc, comme indiqué, PropertyMock ne fonctionne pas avec AttributeError défini comme un side_effect. La solution de contournement est de créer un simple Mock avec un attribut spec défini sur une liste vide comme ceci:

>>> from mock import Mock
>>> m = Mock(spec=[])
>>> m.p
Traceback (most recent call last)
[...]
AttributeError

Comme indiqué dans la documentation:

spec: Cela peut être soit une liste de chaînes, soit un objet existant (une classe ou une instance) agissant comme spécification pour l'objet mock. Si vous passez un objet, une liste de chaînes est formée en appelant dir sur l'objet (en excluant les attributs et méthodes magiques non pris en charge). Accéder à un attribut qui ne figure pas dans cette liste entraînera un AttributeError.

4voto

Alex Hammel Points 335

Er, maintenez la ligne. Est-ce que cela couvre votre cas d'utilisation ?

>>> import mock
>>> m = mock.MagicMock()
>>> m.p

>>> del m.p #!
>>> m.p
Traceback (most recent call last):
     File "", line 1, in 
     File "/home/ahammel/bin/python/mock-1.0.1-py2.6.egg/mock.py", line 664, in __getattr__
         raise AttributeError(name)
     AttributeError: p

Je suis tombé sur cela dans la documentation alors que je cherchais quelque chose de totalement différent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X