[英]Unable to mock __subclasses__ in python
Why does the following code not work? 为什么以下代码不起作用?
>>> 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__'
I think I'm following the documentation on mocking magic methods here. 我想我正在关注模拟魔术方法的文档。 The docs do remark that trying to mock a magic method which is not in the spec will not work.
该文档确实指出,尝试模拟规范中未包含的魔术方法将不起作用。 But why would
__subclasses__
not be in the spec of an autospecced new-style class? 但是为什么
__subclasses__
不在自动指定的新样式类的规范中?
__subclasses__
is not part of the class spec. __subclasses__
不是类规范的一部分。 It is part of the metatype of the class ( type
here). 它是类的元类型的一部分(
type
这里)。
Python always looks up special methods on the type , never directly. Python总是在类型上查找特殊的方法 ,而不是直接查找 。 If and when Python needs to call
__subclasses__
, it'll not do so directly, it'll use type(classobj).__subclasses__(classobj)
to look up the unbound method and pass in the first argument manually. 如果并且当Python需要调用
__subclasses__
,它不会直接调用__subclasses__
,它将使用type(classobj).__subclasses__(classobj)
查找未绑定的方法并手动传递第一个参数。 As such, adding __subclasses__
to the mock of a class is not going to be enough. 因此,
__subclasses__
在类的模拟中添加__subclasses__
是不够的。
The same applies to special methods intended to operate on instances; 这同样适用于旨在对实例进行操作的特殊方法。
Mock
will happily take __add__
or __str__
along when using create_autospec()
, and that works then for instances of the mocked class where Python will use type(mockinstance).__str__(mockinstance)
to invoke the __str__
method. 当使用
create_autospec()
, Mock
会很高兴地使用__add__
或__str__
,并且适用于Mock
类的实例 ,其中Python将使用type(mockinstance).__str__(mockinstance)
来调用__str__
方法。
If your own code calls classobj.__subclasses__()
directly, you'll need to pass in a class mock that explicitly sets that method; 如果您自己的代码直接调用
classobj.__subclasses__()
,则需要传入一个明确设置该方法的类模拟; you can't expect it to be auto-specced here. 您不能期望它会在此处自动指定。
Mocks don't like you setting any valid magic method: 嘲弄者不喜欢您设置任何有效的魔术方法:
>>> 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__'
only non-default magic methods are allowed: 仅允许使用非默认的魔术方法:
>>> m.__dummy__ = Mock()
>>> m.__dummy__
<Mock name='mock.__dummy__' id='4427608656'>
You can create a subclass of A
adding in the __subclass__
method to allow you to mock it: 您可以在
__subclass__
方法中添加A
的子类,以模拟它:
>>> class AMockSpec(A):
... def __subclasses__(self): pass
...
>>> m = create_autospec(AMockSpec)
>>> m.__subclasses__ = Mock()
>>> m.__subclasses__.return_value = ['SomeMockValue']
>>> m.__subclasses__()
['SomeMockValue']
The following does work ( __subclasses__
is available on __class__
): 以下工作正常(
__class__
上提供__subclasses__
):
>>> 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'>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.