unit - Utilizando el mock patch.object de python para cambiar el valor de retorno de un método llamado dentro de otro método
python mock patch (3)
Esto se puede hacer con algo como esto:
# foo.py
class Foo:
def method_1():
results = uses_some_other_method()
# testing.py
from mock import patch
@patch(''Foo.uses_some_other_method''):
def test_some_other_method(mock_some_other_method):
mock_some_other_method.return_value = "specific_value"
foo = Foo()
the_value = foo.method_1()
assert name == "specific_value"
Aquí hay una fuente que puede leer: Parches en el lugar equivocado
¿Es posible simular un valor de retorno de una función llamada dentro de otra función que estoy intentando probar? Me gustaría que el método simulado (que se llamará en muchos métodos que estoy probando) devuelva mis variables especificadas cada vez que se llame. Por ejemplo:
class Foo:
def method_1():
results = uses_some_other_method()
def method_n():
results = uses_some_other_method()
En la prueba de unidad, me gustaría usar simulacro para cambiar el valor de retorno de uses_some_other_method()
para que cada vez que se llame a Foo
, devuelva lo que @patch.object(...)
en @patch.object(...)
Hay dos maneras de hacer esto; con patch y con patch.object
El parche asume que no está importando directamente el objeto sino que está siendo utilizado por el objeto que está probando como se indica a continuación.
#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 está importando directamente el módulo a probar, puede usar patch.object de la siguiente manera:
#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''
En ambos casos, algunos_fn se ''desconectarán'' después de que se complete la función de prueba.
Edición: para simular múltiples funciones, simplemente agregue más decoradores a la función y agregue argumentos para tomar en los parámetros adicionales
@patch.object(foo, ''some_fn'')
@patch.object(foo, ''other_fn'')
def test_foo(test_other_fn, test_some_fn):
...
Tenga en cuenta que cuanto más cerca esté el decorador de la definición de función, más pronto estará en la lista de parámetros.
Permítame aclarar de qué está hablando: quiere probar Foo
en un testcase, que llama al método externo uses_some_other_method
. En lugar de llamar al método real, desea simular el valor de retorno.
class Foo:
def method_1():
results = uses_some_other_method()
def method_n():
results = uses_some_other_method()
Está bien, supongamos que el código anterior está en foo.py
, uses_some_other_method
se define en el módulo bar.py
Aquí está la prueba de unidad:
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 desea cambiar el valor de retorno cada vez que pasa en diferentes argumentos, mock
proporciona side_effect
.