为什么自动指定的模拟Enum
不可迭代(没有__iter__
方法)?
from unittest.mock import create_autospec
from enum import IntEnum
class IE(IntEnum):
Q = 1
W = 2
m = create_autospec(spec=IE, instance=False)
print(hasattr(IE, '__iter__')) # True
print(hasattr(m, '__iter__')) # False
print(m) # <MagicMock spec='IE' id='140008077774128'>
ml = create_autospec(spec=[1,2,3], instance=True)
print(hasattr(ml, '__iter__')) # True
Python版本:
Python 3.10.9 (main, Dec 7 2022, 01:12:00) [GCC 9.4.0] on linux
原因是__iter__
总是必须是实例方法。Enum
基类没有在其上定义__iter__
。它的元类EnumMeta
可以。
Enum
实现了可迭代协议。具体来说,EnumMeta.__iter__
返回类的成员(按定义顺序)。
这就是hasattr(Enum, "__iter__")
返回True
的原因。该属性由它的(元)类定义。
一般来说,您应该谨慎地考虑在自动指定的模拟对象中所反映的内容。更"异国情调";你的属性/方法越不正确,规范就越不可能正确,因为它依赖于自省。如果有疑问,我建议根据需要显式地创建mock属性,而不是依赖于autospec。以下是unittest.mock
中关于自动指定一章的一段话:
[Autospeccing]不是没有警告和限制,然而,这就是为什么它不是默认行为。为了知道spec对象上有哪些属性可用,autospec必须内省(访问属性)spec。当您遍历mock上的属性时,将在底层对原始对象进行相应的遍历。
目前,create_autospec
依赖于dir
来检查应该创建/模拟哪些属性。这本身就带来了很多限制。