无法在python中模拟__subclasses__

时间:2015-05-15 21:20:31

标签: python mocking

为什么以下代码不起作用?

+ [UIImage animatedImageNamed:duration:]

我在这里遵循关于模仿魔术方法的文档。文档表示试图模拟不在规范中的魔术方法是行不通的。但是为什么>>> from mock import * >>> class A(object): ... pass ... >>> mock = create_autospec(A) >>> mock.foo = Mock() # this works >>> mock.__bar__ = Mock() # this works too >>> mock.__subclasses__ = Mock() # this fails AttributeError: Mock object has no attribute '__subclasses__' 会出现在自动指定的新式类的规范中?

2 个答案:

答案 0 :(得分:1)

__subclasses__ 不是类规范的一部分。它是类的元类型的一部分(此处为type)。

Python总是looks up special methods on the type,永远不会直接。如果Python需要调用__subclasses__,它不会直接调用它,它会使用type(classobj).__subclasses__(classobj)来查找未绑定的方法并手动传入第一个参数。因此,将__subclasses__添加到类的模拟中是不够的。

这同样适用于打算对实例进行操作的特殊方法;使用Mock时,__add__会愉快地使用__str__create_autospec(),然后在Python将使用的模拟类的实例中使用type(mockinstance).__str__(mockinstance) { {1}}调用__str__方法。

如果您自己的代码直接调用classobj.__subclasses__(),则您需要传入一个显式设置该方法的类模拟;你不能指望它在这里自动编制。

模拟不喜欢你设置任何有效的魔术方法:

>>> m = create_autospec(A)
>>> m.__add__ = Mock()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/mock.py", line 767, in __setattr__
    raise AttributeError("Mock object has no attribute '%s'" % name)
AttributeError: Mock object has no attribute '__add__'

只允许使用非默认魔术方法:

>>> m.__dummy__ = Mock()
>>> m.__dummy__
<Mock name='mock.__dummy__' id='4427608656'>

您可以使用A方法创建__subclass__的子类,以便模拟它:

>>> class AMockSpec(A):
...     def __subclasses__(self): pass
...
>>> m = create_autospec(AMockSpec)
>>> m.__subclasses__ = Mock()
>>> m.__subclasses__.return_value = ['SomeMockValue']
>>> m.__subclasses__()
['SomeMockValue']

答案 1 :(得分:0)

以下工作正常(__subclasses__上提供__class__):

>>> from mock import *
>>> class A(object):
...     pass
...
>>> m = create_autospec(A)
>>> m.__class__.__subclasses__()
[]
>>> class B(A): pass
...
>>> m.__class__.__subclasses__()
[<class '__main__.B'>]
>>> m.__class__.__subclasses__ = Mock()
>>> m.__class__.__subclasses__()
<Mock name='mock()' id='4372594896'>