Cabe señalar que varias de las respuestas aquí parchearán el decorador para toda la sesión de prueba en lugar de una sola instancia de prueba; que puede ser indeseable. A continuación, se explica cómo parchear un decorador que solo persiste a través de una única prueba.
Nuestra unidad para ser probada con el decorador no deseado:
from app.decorators import func_decor
@func_decor
def unit_to_be_tested():
pass
Desde el módulo de decoradores:
def func_decor(func):
def inner(*args, **kwargs):
print "Do stuff we don't want in our test"
return func(*args, **kwargs)
return inner
Para cuando nuestra prueba se recopila durante una ejecución de prueba, el decorador no deseado ya se ha aplicado a nuestra unidad bajo prueba (porque eso ocurre en el momento de la importación). Para deshacernos de eso, necesitaremos reemplazar manualmente el decorador en el módulo del decorador y luego volver a importar el módulo que contiene nuestra UUT.
Nuestro módulo de prueba:
from unittest import TestCase
from app import uut
from app import decorators
import imp
from mock import patch
class TestUUT(TestCase):
def setUp(self):
def kill_patches():
patch.stopall()
imp.reload(uut)
self.addCleanup(kill_patches)
patch('app.decorators.func_decor', lambda x: x).start()
imp.reload(uut)
La devolución de llamada de limpieza, kill_patches, restaura el decorador original y lo vuelve a aplicar a la unidad que estábamos probando. De esta manera, nuestro parche solo persiste a través de una única prueba en lugar de toda la sesión, que es exactamente como debería comportarse cualquier otro parche. Además, dado que la limpieza llama a patch.stopall (), podemos iniciar cualquier otro parche en el setUp () que necesitemos y se limpiarán todo en un solo lugar.
Lo importante que hay que entender sobre este método es cómo afectará la recarga a las cosas. Si un módulo tarda demasiado o tiene una lógica que se ejecuta en la importación, es posible que solo deba encogerse de hombros y probar el decorador como parte de la unidad. :( Esperemos que tu código esté mejor escrito que eso. ¿Verdad?
Si a uno no le importa si el parche se aplica a toda la sesión de prueba , la forma más sencilla de hacerlo es en la parte superior del archivo de prueba:
from mock import patch
patch('app.decorators.func_decor', lambda x: x).start()
from app import uut
Asegúrese de parchear el archivo con el decorador en lugar del alcance local de la UUT y de iniciar el parche antes de importar la unidad con el decorador.
Curiosamente, incluso si se detiene el parche, todos los archivos que ya se importaron tendrán el parche aplicado al decorador, que es lo contrario de la situación con la que comenzamos. Tenga en cuenta que este método parcheará cualquier otro archivo en la ejecución de prueba que se importe posteriormente, incluso si ellos mismos no declaran un parche.