简体   繁体   English

Python mock.patch autospec 一个具有属性的类

[英]Python mock.patch autospec a class with properties

I have a class that defines some properties with the @property decorator.我有一个用@property 装饰器定义一些属性的类。 When I patch that class and set autospec=True, i expect the property to behave as as it is spec'd当我修补该类并设置 autospec=True 时,我希望该属性的行为与规范一样

class MyClass(object):

    def __init__(self):
        self.will_not_be_mocked = 'not mocked'

    @property
    def will_be_mocked(self):
        return 'mocked property'

Expected Behavior:预期行为:

When I access the will_be_mocked property on an instance, it behaves like a string attribute.当我访问实例上的 will_be_mocked 属性时,它的行为就像一个字符串属性。

>>> my_obj = MyClass()
>>> my_obj.will_be_mocked
'mocked property'

and it is not callable它不可调用

>>> my_obj.will_be_mocked()
TypeError: 'str' object is not callable

So this test should pass:所以这个测试应该通过:

with self.assertRaises(TypeError):
    my_obj.will_be_mocked()

Observed Behavior:观察到的行为:

When I patch the class, and set autospec=True, The property is included in the mock's spec as expected, however, it becomes a MagicMock, and is callable.当我修补该类并设置 autospec=True 时,该属性按预期包含在模拟的规范中,但是,它变成了一个 MagicMock,并且是可调用的。 So any code which tried to execute that property could pass the unittest and fail in production因此,任何试图执行该属性的代码都可能通过单元测试并在生产中失败

@patch('__main__.MyClass', autospec=True)
def test_MyClass(self, MyClass):
    my_obj = MyClass()
    with self.assertRaises(TypeError):
        my_obj.will_be_mocked()

AssertionError: TypeError not raised

Objective:客观的:

I want to define the class in such a way that it is easy to mock with autospec.我想以一种易于使用 autospec 进行模拟的方式定义该类。 This is why I'm trying to define properties instead of just adding attributes in __init__ .这就是为什么我试图定义属性而不是仅仅在__init__添加属性。

I want to define the class in such a way that it is easy to mock with autospec我想以一种易于使用 autospec 进行模拟的方式定义该类

The autospec is normally used in situations where everything about a class is to be mocked or faked. autospec 通常用于类的所有内容都将被模拟或伪造的情况。 It is not the case in your example, patching or fake 1 and only one class attribute is needed.在您的示例中,情况并非如此,修补或伪造 1 并且只需要一个类属性。

Here is an example:下面是一个例子:

class Base(object):

@property
def cls_property(self):
    return 'cls_property'

class TestBase(unittest.TestCase):

def test_cls_property_with_property(self):
    """
    """
    with mock.patch('app.Base.cls_property', new_callable=mock.PropertyMock) as mock_cls_property:
        mock_cls_property.return_value = 'mocked_cls_property'
        base = Base()
        self.assertEqual(base.cls_property, 'mocked_cls_property')

        with self.assertRaises(Exception):
            base.cls_property()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM