我有这样的东西:
from unittest.mock import MagicMock
class A:
pass
class B(A):
pass
mock_B = MagicMock(spec_set=B)
assert issubclass(mock_B, A) # TypeError: issubclass() arg 1 must be a class
我怎样才能让这个通过?
isinstance 和 Mocking 有很多不同的答案,但从那里我无法弄清楚。
这里的问题是,你想将
MagicMock
的实例视为类,但 Python 中的对象只有当它是 type
的实例时才能被视为实际的类。
一种解决方法是创建一个与要模拟的类具有相同基类的类,但通过使用定义了
__getattribute__
方法的元类创建该类,将其所有属性查找委托给模拟对象。但是,生成的“类”的行为不会像类,因为所有属性查找现在委托给的模拟对象没有类似类的属性。因此,我们可以通过将模拟对象中不可用的属性默认为被模拟的类来使其表现得更像一个类:
from unittest.mock import MagicMock
def mock_class(cls):
class meta_mocked_class(type):
def __getattribute__(self, name):
try:
return getattr(mock, name)
except AttributeError:
return getattr(cls, name)
mock = MagicMock(spec_set=cls)
return meta_mocked_class(cls.__name__, cls.__bases__, {})
这样:
class A:
pass
class B(A):
def foo(self):
pass
mock_B = mock_class(B)
assert issubclass(mock_B, A)
print(mock_B)
print(mock_B.foo)
print(mock_B.__name__)
print(mock_B.__bases__)
通过
issubclass
断言并输出:
<class '__main__.B'>
<MagicMock name='mock.foo' id='1970990059024'>
B
(<class '__main__.A'>,)
演示:在线试用!