mock example python unit-testing mocking decorator monkeypatching

python - example - pytest mock



Cómo burlarse de una función decorada (1)

Python aplica el decorador al cargar el módulo, por lo que establecer function_to_be_mocked para mock_function en test_decoratorated_mocked cambiará esa función en una función no decorada.

Tendrá que agregar manualmente el decorador de nuevo si desea simular que function_to_be_mocked :

mydecorator.function_to_be_mocked = mydecorator.my_decorator(mock_function)

Por razones de prueba, necesito poder burlarme de la función interior / original de una decorada que se usa en otro lugar:

En mydecorator.py:

def my_decorator(f): def wrapped_f(): print "decorated" f() return wrapped_f @my_decorator def function_to_be_mocked(): print ''original'' def function_to_be_mocked_undecorated(): print ''original'' def run_decorated(): function_to_be_mocked() def run_undecorated(): decorated_funtion = my_decorator(function_to_be_mocked_undecorated) decorated_funtion()

Como puede ver, tengo varias versiones de la función original function_to_be_mocked, una con el decorador my_decorator y otra ''naked''. La función runner run_decorated () llama a la versión decorada de function_to_be_mocked y run_undecorated () llama a la versión no decorada y aplica el decorador ''manualmente''. El resultado de ambos es el mismo:

decorated original

Ahora quiero probar la función runner pero necesito burlarme de la función original function_to_be_mocked pero también debe decorarse la versión simulada:

import unittest import mydecorator from mock import patch def mock_function(): print ''mockified'' class Test(unittest.TestCase): @patch(''mydecorator.function_to_be_mocked_undecorated'') def test_undecorated_mocked(self, mock_function_to_be_mocked_undecorated): mydecorator.function_to_be_mocked_undecorated = mock_function mydecorator.run_undecorated() assert 1==0 @patch(''mydecorator.function_to_be_mocked'') def test_decoratorated_mocked(self, mock_function_to_be_mocked): mydecorator.function_to_be_mocked = mock_function mydecorator.run_decorated() assert 1==0

Esto funciona como se esperaba para la versión no decorada test_undecorated_mocked:

decorated mockified

Pero la versión decorada da:

mockified

entonces el decorador desapareció.

¿Es posible hacer que la versión decorada funcione del mismo modo que la versión no decorada, donde el decorador se aplica "manualmente"?

Traté de exponer la función interna en el decorador sin éxito.

Vi esta pregunta. ¿Cómo se burla de una función que tiene el decorador aplicado en una prueba unitaria? pero esto no me ayuda.