使用unittest.mock.patch时,默认情况下为什么autospec不为True? [英] When using unittest.mock.patch, why is autospec not True by default?

查看:132
本文介绍了使用unittest.mock.patch时,默认情况下为什么autospec不为True?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用模拟对函数进行修补时,可以选择将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?

推荐答案

解释此问题的唯一清晰方法是实际引用

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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆