2015-03-24 3 views
5

This сценарии не удается:TypeError: несвязанный метод при попытке издеваться classmethod

import mock 

class MyClass(object): 

    @classmethod 
    def my_method(cls): 
     print('my_method') 

def mocked_method(cls): 
    print('I want this method to get called') 

with mock.patch.object(MyClass, 'my_method', mocked_method): 
    MyClass.my_method() 

Исключение:

Traceback (most recent call last): 
    File "/home/foo/tmp/test_mocking_classmethod.py", line 14, in <module> 
    MyClass.my_method() 
TypeError: unbound method mocked_method() must be called with MyClass instance as first argument (got nothing instead) 

ответ

6

функции Python являются descriptors и Python связывает их к примеру они смотрели на, или в случае classmethod, классу. Поскольку вы не использовали декоратор classmethod в функции замены, он ошибочно связан (как обычный метод, поэтому не передается cls).

Просто оберните цель в classmethod декоратора вручную:

with mock.patch.object(MyClass, 'my_method', classmethod(mocked_method)): 
    MyClass.my_method() 

Здесь я применил @classmethod декоратора вручную, но вы также можете просто использовать его по назначению, как декоратор, непосредственно на целевой функции:

@classmethod 
def mocked_method(cls): 
    print('I want this method to get called') 

with mock.patch.object(MyClass, 'my_method', mocked_method): 
    MyClass.my_method() 

Демо:

>>> import mock 
>>> class MyClass(object): 
...  @classmethod 
...  def my_method(cls): 
...   print('my_method') 
... 
>>> def mocked_method(cls): 
...  print('I want this method to get called') 
... 
>>> with mock.patch.object(MyClass, 'my_method', classmethod(mocked_method)): 
...  MyClass.my_method() 
... 
I want this method to get called 
+0

Это и некоторые additiona l документация относительно издевательских несвязанных методов https://docs.python.org/3.5/library/unittest.mock-examples.html#mocking-unbound-methods помогла мне немного – Marc

Смежные вопросы