unittest unit test mock python unit-testing mocking patch

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 .