Fonction python moqueuse basée sur des arguments d’entrée

Nous utilisons Mock for python depuis un moment.

Maintenant, nous avons une situation dans laquelle nous voulons nous moquer d’une fonction

def foo(self, my_param): #do something here, assign something to my_result return my_result 

Normalement, la façon de se moquer de cela serait (en supposant que foo faisant partie d’un object)

 self.foo = MagicMock(return_value="mocked!") 

Même si j’appelle foo () plusieurs fois, je peux utiliser

 self.foo = MagicMock(side_effect=["mocked once", "mocked twice!"]) 

Maintenant, je suis confronté à une situation dans laquelle je veux retourner une valeur fixe lorsque le paramètre d’entrée a une valeur particulière. Donc, si nous disons “mon_param” est égal à “quelque chose” alors je veux retourner “my_cool_mock”

Cela semble être disponible sur mockito pour python

 when(dummy).foo("something").thenReturn("my_cool_mock") 

J’ai cherché à obtenir la même chose avec Mock sans succès?

Des idées?

Si side_effect est une fonction, quel que soit le retour de cette fonction, quels sont les appels à la simulation. La fonction side_effect est appelée avec les mêmes arguments que le simulacre. Cela vous permet de varier dynamicment la valeur de retour de l’appel, en fonction de l’entrée:

 >>> def side_effect(value): ... return value + 1 ... >>> m = MagicMock(side_effect=side_effect) >>> m(1) 2 >>> m(2) 3 >>> m.mock_calls [call(1), call(2)] 

http://www.voidspace.org.uk/python/mock/mock.html#calling

Comme indiqué à l’ object Python Mock avec la méthode appelée plusieurs fois

Une solution consiste à écrire mon propre side_effect

 def my_side_effect(*args, **kwargs): if args[0] == 42: return "Called with 42" elif args[0] == 43: return "Called with 43" elif kwarg['foo'] == 7: return "Foo is seven" mockobj.mockmethod.side_effect = my_side_effect 

Ça fait le tour

L’effet secondaire prend une fonction (qui peut aussi être une fonction lambda ), donc pour des cas simples, vous pouvez utiliser:

 m = MagicMock(side_effect=(lambda x: x+1)) 

Juste pour montrer une autre façon de le faire:

 def mock_isdir(path): return path in ['/var/log', '/var/log/apache2', '/var/log/tomcat'] with mock.patch('os.path.isdir') as os_path_isdir: os_path_isdir.side_effect = mock_isdir 

Je sais que c’est une question assez ancienne, pourrait aider comme une amélioration en utilisant python lamdba

 self.some_service.foo.side_effect = lambda *args:"Called with 42" \ if args[0] == 42 \ else "Called with 42" if args[0] == 43 \ else "Called with 43" if args[0] == 43 \ else "Called with 45" if args[0] == 45 \ else "Called with 49" if args[0] == 49 else None