Anula el decorador de parches de Python Mock
mock install (1)
Tengo una clase Python TestCase
donde todos los métodos de prueba, excepto uno, necesitan parchear un objeto de la misma manera. El otro método necesita algún otro comportamiento del mismo objeto. Estoy usando simulacro , así que lo hice:
@mock.patch(''method_to_patch'', mock.Mock(return_value=1))
class Tests(TestCase):
@mock.patch(''method_to_patch'', mock.Mock(return_value=2))
def test_override(self):
(....)
Pero eso no está funcionando. Cuando se ejecuta test_override
, todavía llama al comportamiento parchado del decorador de clase.
Después de mucha depuración, descubrí que durante la construcción de TestSuite
, se @patch
al @patch
around test_override
antes que al de Tests
, y dado que mock
aplicar los parches en orden, el decorador de clases está anulando el decorador de métodos.
¿Es correcto este orden? Esperaba lo opuesto y no estoy seguro de cómo anular el parche ... ¿Tal vez con una declaración?
Bueno, resulta que una buena noche de sueño y una ducha fría me hicieron repensar todo el asunto. Todavía soy muy nuevo en el concepto de burla, por lo que todavía no se ha hundido del todo bien.
El caso es que no hay necesidad de anular el parche a un objeto burlado. Es un objeto burlado y eso significa que puedo hacer que haga cualquier cosa. Así que mi primer intento fue:
@mock.patch(''method_to_patch'', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
method_to_patch.return_value = 2
(....)
Eso funcionó, pero tuvo el efecto secundario de cambiar el valor de retorno de todas las pruebas siguientes. Entonces intenté:
@mock.patch(''method_to_patch'', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
method_to_patch.return_value = 2
(....)
method_to_patch.return_value = 1
Y funcionó como un encanto. Pero parecía demasiado código. Entonces fui por el camino de la gestión del contexto, así:
@mock.patch(''method_to_patch'', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
with mock.patch(''method_to_patch'', mock.Mock(return_value=2):
(....)
Creo que parece más claro y más conciso.
Acerca del orden en que se aplicaron los decoradores de patch
, en realidad es el orden correcto. Al igual que los decoradores apilados se aplican desde abajo hacia arriba, se supone que un decorador de métodos debe llamarse antes que el decorador de clases. Supongo que tiene sentido, solo esperaba el comportamiento contrario.
De todos modos, espero que esto ayude a una pobre alma novata como la mía en el futuro.