That is correct, yes. In order for the class to be passed on to the decorator, it must already be built - which meant that its fields and methods already have to be ready and assigned. Thus, the decorator of the method will have already been executed:
>>> def decorador(x):
... print 'decorando ' + str(x)
... return x
...
>>> @decorador
... class Foo(object):
... @decorador
... def bar():
... pass
...
decorando <function bar at 0x00C7C2F0>
decorando <class '__main__.Foo'>
The simplest solution I can propose [if this patch is overwriting itself] is for you to assign the particular method only after you have created the class:
@mock.patch('metodo_alvo', mock.Mock(return_value=1))
class Tests(TestCase):
...
@mock.patch('metodo_alvo', mock.Mock(return_value=2))
def test_override(self):
(....)
Tests.test_override = test_override
An alternative, if this doesn’t work for any reason (I don’t know the Python Mock), would be to create your own decorator that would "mark" the method in which it is applied, and not apply it again when applying it to the class:
from types import FunctionType
def meu_patch(f, *args, **kwargs):
if isinstance(f, FunctionType):
ret = mock.patch(f, *args, **kwargs) # Aplica o patch ao método
ret.__marcado__ = True # Marca-o, para que o patch não seja reaplicado
return ret
elif isinstance(f, type):
for k,v in f.__dict__.items():
if isinstance(v, FunctionType) and not getattr(v, '__marcado__', False):
f[k] = mock.patch(v, *args, **kwargs) # Aplica o patch aos métodos que não
# foram previamente aplicados
return f
(note: this "marking" may be unnecessary if the result of a previous application of patch
has some distinct characteristic; it would be the result at all times of the kind MagicMock
? If yes, just test this instead of using an extra attribute.)
One last alternative would be to use metaclasses, but I don’t think it would bring any benefit compared to previous methods - just more complexity.