为什么自动指定的枚举模拟不可迭代(没有__iter__方法)?



为什么自动指定的模拟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来检查应该创建/模拟哪些属性。这本身就带来了很多限制。

最新更新