Est-il possible de simuler une valeur de retour d'une fonction appelée dans une autre fonction que je tente de tester? Je voudrais que la méthode fausse (qui sera appelée dans beaucoup de méthodes que je teste) renvoie mes variables spécifiées à chaque appel. Par exemple:
class Foo:
def method_1():
results = uses_some_other_method()
def method_n():
results = uses_some_other_method()
Dans le test unitaire, je voudrais utiliser mock pour modifier la valeur de retour de uses_some_other_method()
de sorte que chaque fois qu'il est appelé dans Foo
, il renvoie ce que j'ai défini dans @patch.object(...)
Vous pouvez le faire de deux manières. avec patch et avec patch.object
Le correctif suppose que vous n'importez pas directement l'objet, mais qu'il est utilisé par l'objet que vous testez, comme indiqué ci-dessous.
#foo.py
def some_fn():
return 'some_fn'
class Foo(object):
def method_1(self):
return some_fn()
#bar.py
import foo
class Bar(object):
def method_2(self):
tmp = foo.Foo()
return tmp.method_1()
#test_case_1.py
import bar
from mock import patch
@patch('foo.some_fn')
def test_bar(mock_some_fn):
mock_some_fn.return_value = 'test-val-1'
tmp = bar.Bar()
assert tmp.method_2() == 'test-val-1'
mock_some_fn.return_value = 'test-val-2'
assert tmp.method_2() == 'test-val-2'
Si vous importez directement le module à tester, vous pouvez utiliser patch.object comme suit:
#test_case_2.py
import foo
from mock import patch
@patch.object(foo, 'some_fn')
def test_foo(test_some_fn):
test_some_fn.return_value = 'test-val-1'
tmp = foo.Foo()
assert tmp.method_1() == 'test-val-1'
test_some_fn.return_value = 'test-val-2'
assert tmp.method_1() == 'test-val-2'
Dans les deux cas, some_fn sera "irréprochable" une fois la fonction de test terminée.
Edit: Afin de simuler plusieurs fonctions, il suffit d’ajouter des décorateurs à la fonction et d’ajouter des arguments pour intégrer les paramètres supplémentaires.
@patch.object(foo, 'some_fn')
@patch.object(foo, 'other_fn')
def test_foo(test_other_fn, test_some_fn):
...
Notez que plus le décorateur est proche de la définition de la fonction, plus tôt il se trouve dans la liste des paramètres.
Cela peut être fait avec quelque chose comme ça:
# foo.py
class Foo:
def method_1():
results = uses_some_other_method()
# testing.py
from mock import patch
@patch('Foo.uses_some_other_method', return_value="specific_value"):
def test_some_other_method(mock_some_other_method):
foo = Foo()
the_value = foo.method_1()
assert the_value == "specific_value"
Voici une source que vous pouvez lire: Patching au mauvais endroit
Laissez-moi clarifier de quoi vous parlez: vous voulez tester Foo
dans un cas de test, qui appelle une méthode externe uses_some_other_method
. Au lieu d'appeler la méthode réelle, vous voulez vous moquer de la valeur de retour.
class Foo:
def method_1():
results = uses_some_other_method()
def method_n():
results = uses_some_other_method()
Ok, supposons que le code ci-dessus soit en foo.py
, uses_some_other_method
est défini dans le module bar.py
. Voici le plus modeste:
import unitest
import mock
from foo import Foo
class TestFoo(unittest.TestCase):
def setup(self):
self.foo = Foo()
@mock.patch('foo.uses_some_other_method')
def test_method_1(self, mock_method):
mock_method.return_value = 3
self.foo.method_1(*args, **kwargs)
mock_method.assert_called_with(*args, **kwargs)
Si vous voulez changer la valeur de retour chaque fois que vous passez dans différents arguments, mock
fournit side_effect
.