[英]python patch with side_effect on Object's method is not called with self
我在patch.object中遇到了side_effect參數的令人驚訝的行為,其中替換原始函數的函數沒有收到self
class Animal():
def __init__(self):
self.noise = 'Woof'
def make_noise(self):
return self.noise
def loud(self):
return self.noise.upper() + '!!'
from unittest.mock import patch
dog = Animal()
dog.make_noise()
with patch.object(Animal, 'make_noise', side_effect=loud):
dog.make_noise()
這給:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/lustre/home/production/Applications/python/python-3.4.4/lib/python3.4/unittest/mock.py", line 902, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "/lustre/home/production/Applications/python/python-3.4.4/lib/python3.4/unittest/mock.py", line 968, in _mock_call
ret_val = effect(*args, **kwargs)
TypeError: loud() missing 1 required positional argument: 'self'
如果我將loud
功能更改為
def loud(*args, **kwargs):
print(args)
print(kwargs)
我得到以下輸出:
()
{}
有沒有辦法從一個對象替換一個函數,仍然接收自己?
self
僅為綁定方法提供 (因為函數是描述符 )。 Mock
對象不是這樣的方法,並且side_effect
函數沒有綁定,因此self
確實不會被傳入。
如果必須訪問side_effect
對象中的實例,則必須使用實際函數在類上修補該函數:
with patch.object(Animal, 'make_noise', new=loud):
現在make_noise
被Animal
類上的loud
函數取代,所以它將被綁定:
>>> with patch.object(Animal, 'make_noise', new=loud):
... dog.make_noise()
...
'WOOF!!'
另一種方法是設置autospec=True
,此時mock
將使用實際函數來模擬make_noise()
:
>>> with patch.object(Animal, 'make_noise', autospec=True, side_effect=loud):
... dog.make_noise()
...
'WOOF!!'
另請參閱模擬入門 部分中的Mocking Unbound Methods部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.