【问题标题】:Python PropertyMock side effect with AttributeError and ValueError带有 AttributeError 和 ValueError 的 Python PropertyMock 副作用
【发布时间】:2013-08-14 15:36:22
【问题描述】:

我试图模拟一个类的属性(@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

【问题讨论】:

  • 您第二次收到错误,因为您通过再次调用 PropertyMock 使 m.p 的副作用与 AttributeError 不同(我不确定如何以及为什么)。您可以像这样更改没有错误的副作用: m.p.side_effect = ValueError
  • @kren470:啊,抱歉我的问题不清楚。第二个行为是正确的。第一个不是。我希望在这两种情况下都会引发异常。问题已编辑。
  • 对我来说同样的行为。我已提交错误报告:code.google.com/p/mock/issues/detail?id=219
  • @AlexHammel:谢谢!我会留意那个错误。
  • @Sardathrion 没问题!我预计问题在于 Mock 类中有某种深层魔法可以捕获 AttributeErrors。我们将看到开发人员在错误报告中所说的内容,但使用 PropertyMock 解决这个问题可能是不切实际的。不过,绝对应该有一种方法可以让 Mock 引发 AttributeError。可能需要等待几个版本。

标签: python mocking


【解决方案1】:

我知道这个问题很老,但我刚刚遇到了同样的问题并发现了这个问题。此外,大约两年前提交的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。

【讨论】:

  • 问题可能是旧的,但答案是正确的。谢谢!
  • 除非您希望 AttributeError 消息为 "Value cannot be negative!",否则您就不走运了。
【解决方案2】:

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

>>> 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

【讨论】:

  • 不,它没有。我将扩展问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 2011-09-27
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多