J'utilise unittest.mock
, cette merveilleuse bibliothèque. Cependant, j'ai été surpris par un comportement inattendu, et je ne vois pas une solution évidente. Je l'utilise pour mes tests unitaires et il est essentiel de comprendre parfaitement comment il se comporte pour avoir des tests utiles.Comment tester si la méthode de l'instance est appelée avec "self" en se moquant?
Je sais que le code ci-dessous dans show_bar
est cassé, il appelle un classmethod au lieu de la méthode d'instance. Cependant, tous mes mock
unittests passent:
code contenant un bug:
class Foo(object):
def bar(self):
return "bar"
def show_bar(self):
return Foo.bar()
utilisation prévue:
foo = Foo()
assert foo.show_bar() == "bar"
# => throw exception: bar() missing 1 required positional argument: 'self'
UnitTest tente en vain de rattraper cette erreur avec mock
:
from unittest.mock import patch
with patch.object(Foo, 'bar', return_value="bar") as mock:
foo = Foo()
assert foo.show_bar() == "bar"
mock.assert_called_once()
# => no errors
Idéalement, je voudrais affirmer que bar
est appelée avec self.bar()
et NON Foo.bar()
; ce qui est faux. Malheureusement, en utilisant mock.assert_called_with()
ne prend pas en compte le paramètre self
ni cls
, donc je suis un peu confus.
EDIT: Essayer de clarifier. Je suis à la recherche de bonnes pratiques pour utiliser la bibliothèque unittest.mock
lorsque nous avons besoin de patcher la méthode d'un objet. Il ne semble pas clair pour moi comment le patcher, actuellement je n'ai aucun moyen d'affirmer si elle appelle self.bar
ou Foo.bar
.
ne vous moquez pas quoi que ce soit, il suffit d'appeler 'f = Foo(); f.bar() 'dans votre code de test. Avec l'implémentation interrompue, cela déclenchera un 'TypeError', ce qui fera échouer le test. –
Aussi et FWIW, cela n'a rien à voir avec 'classmethod' - dans votre exemple' Foo.bar' est une méthode d'instance indépendante. –
Désolé, le code est trop simplifié et j'ai * besoin * d'utiliser le mock car le code réel de la méthode n'est pas callable sans se moquer de sa valeur de retour. De plus, quand le développeur 'show_bar' appelle' Foo.bar() ', je supposais que' Foo.bar' est soit une méthode de classe, soit une méthode static. Cela semble une déclaration raisonnable? – Doomsday