問題描述
當您使用 mock 修補函數時,您可以選擇將 autospec 指定為 True:
When you patch a function using mock, you have the option to specify autospec as True:
如果您設置 autospec=True ,則使用規范創建模擬從被替換的對象.模擬的所有屬性也將具有對象的相應屬性的規范更換.被模擬的方法和函數將有它們的參數檢查并在錯誤調用它們時引發 TypeError簽名.
If you set autospec=True then the mock with be created with a spec from the object being replaced. All attributes of the mock will also have the spec of the corresponding attribute of the object being replaced. Methods and functions being mocked will have their arguments checked and will raise a TypeError if they are called with the wrong signature.
(http://www.voidspace.org.uk/python/mock/patch.html)
我想知道為什么這不是默認行為?當然,我們幾乎總是希望捕捉傳遞給我們修補的任何函數的錯誤參數?
I'm wondering why this isn't the default behaviour? Surely we would almost always want to catch passing incorrect parameters to any function we patch?
推薦答案
解釋這一點的唯一明確方法是實際引用 documentation 關于使用自動規范的缺點以及為什么在使用時應該小心:
The only clear way to explain this, is to actually quote the documentation on the downside of using auto-speccing and why you should be careful when using it:
然而,這并非沒有警告和限制,這就是它的原因不是默認行為.為了知道什么是屬性在 spec 對象上可用,autospec 必須自省(訪問屬性)規范.當您遍歷模擬上的屬性時原始對象的相應遍歷發生在兜帽.如果您指定的任何對象具有屬性或描述符可以觸發代碼執行,那么您可能無法使用自動規格.另一方面,設計你的對象要好得多這樣自省是安全的 [4].
This isn’t without caveats and limitations however, which is why it is not the default behaviour. In order to know what attributes are available on the spec object, autospec has to introspect (access attributes) the spec. As you traverse attributes on the mock a corresponding traversal of the original object is happening under the hood. If any of your specced objects have properties or descriptors that can trigger code execution then you may not be able to use autospec. On the other hand it is much better to design your objects so that introspection is safe [4].
一個更嚴重的問題是實例屬性很常見在 init 方法中創建并且不存在于類中全部.autospec 不知道任何動態創建的屬性和將 api 限制為可見屬性.
A more serious problem is that it is common for instance attributes to be created in the init method and not to exist on the class at all. autospec can’t know about any dynamically created attributes and restricts the api to visible attributes.
我認為這里的關鍵要點是注意這一行:autospec 無法知道任何動態創建的屬性并將 api 限制為可見屬性
I think the key takeaway here is to note this line: autospec can’t know about any dynamically created attributes and restricts the api to visible attributes
因此,為了更清楚地說明自動檢測中斷的示例,從文檔中獲取的這個示例顯示了這一點:
So, to help being more explicit with an example of where autospeccing breaks, this example taken from the documentation shows this:
>>> class Something:
... def __init__(self):
... self.a = 33
...
>>> with patch('__main__.Something', autospec=True):
... thing = Something()
... thing.a
...
Traceback (most recent call last):
...
AttributeError: Mock object has no attribute 'a'
如您所見,自動規范不知道在創建 Something
對象時會創建屬性 a
.
As you can see, auto-speccing has no idea that there is an attribute a
being created when creating your Something
object.
為您的實例屬性賦值并沒有錯.
There is nothing wrong with assigning a value to your instance attribute.
觀察下面的函數示例:
import unittest
from mock import patch
def some_external_thing():
pass
def something(x):
return x
class MyRealClass:
def __init__(self):
self.a = some_external_thing()
def test_thing(self):
return something(self.a)
class MyTest(unittest.TestCase):
def setUp(self):
self.my_obj = MyRealClass()
@patch('__main__.some_external_thing')
@patch('__main__.something')
def test_my_things(self, mock_something, mock_some_external_thing):
mock_some_external_thing.return_value = "there be dragons"
self.my_obj.a = mock_some_external_thing.return_value
self.my_obj.test_thing()
mock_something.assert_called_once_with("there be dragons")
if __name__ == '__main__':
unittest.main()
所以,我只是說對于我的測試用例,我想確保 some_external_thing()
方法不會影響我的單元測試的行為,所以我只是分配我的實例屬性每個 mock_some_external_thing.return_value = "there be dragons"
的模擬.
So, I'm just saying for my test case I want to make sure that the some_external_thing()
method does not affect the behaviour of my unittest, so I'm just assigning my instance attribute the mock per mock_some_external_thing.return_value = "there be dragons"
.
這篇關于使用unittest.mock.patch時,為什么autospec默認不是True?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!