簡體   English   中英

不使用self調用帶有side_effect的對象方法的python補丁

[英]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_noiseAnimal類上的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM