具有AttributeError和ValueError的Python PropertyMock副作用

时间:2013-08-14 15:36:22

标签: python mocking

我正在尝试模拟一个类的属性(@property装饰器)并且遇到了这种不正确的行为:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=AttributeError)
 >>> m.p
 <MagicMock name='mock.p' id='63150736'>

正确的行为是:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=ValueError)
 >>> m.p
Traceback (most recent call last)
[...]
ValueError

我无法理解为什么设置不同的异常会给我不同的结果。两种情况下的预期结果都是应该提出异常!因此,In [4]行应该引发AttributeError。它没有。

任何人都想开导我吗?

附录:我要检查的属性会进行一些巧妙的检查,以确定传递的值是否合理。如果所述值不合理,则返回AttributeError,因为我理解这是Python中的正确异常。所以,我需要检查使用该属性的代码是否失败以及成功。因此,使用MagicMock来模拟属性并引发异常。一个简单的例子是:

@x.setter
def x(self, value):
    if value < 0:
         raise AttributeError("Value cannot be negative!")
    self._x = value

2 个答案:

答案 0 :(得分:11)

我知道这个问题很老,但我遇到了同样的问题,发现了这个问题。大约两年前提交的bug report似乎也没有得到任何关注,所以我想我会分享我发现的解决方案以防其他人遇到这个问题。

因此,如上所述PropertyMock不适用AttributeError设置为side_effect。解决方法是创建一个简单的Mock,其spec属性设置为空list,如下所示:

>>> from mock import Mock
>>> m = Mock(spec=[])
>>> m.p
Traceback (most recent call last)
[...]
AttributeError

docs中所述:

  

spec:这可以是字符串列表,也可以是充当模拟对象规范的现有对象(类或实例)。如果传入一个对象,则通过在对象上调用dir来形成字符串列表(不包括不受支持的魔术属性和方法)。 访问不在此列表中的任何属性将引发AttributeError。

答案 1 :(得分:3)

呃,拿着电话。这是否涵盖了您的用例?

>>> import mock
>>> m = mock.MagicMock()
>>> m.p
<MagicMock name='mock.p' id='139756843423248'>
>>> del m.p #!
>>> m.p
Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "/home/ahammel/bin/python/mock-1.0.1-py2.6.egg/mock.py", line 664, in __getattr__
         raise AttributeError(name)
     AttributeError: p

我在寻找完全不同的东西的过程中偶然发现了the docs