如何在测试运行时类型检查期间模拟 Python class?

How to mock a Python class during testing for runtime typing checks?

我有一些应用程序方法使用 @typeguard.typechecked 装饰器对传递的参数执行运行时检查:

class SalesDeal:
    pass

@typechecked
def do_something(deal: SalesDeal):
   pass

在一个测试中,我有一个假的 class FakeSalesDeal,它为 SalesDeal 实现了一个最小的模拟(这在现实中是一个非常复杂的 class):

class FakeSalesDeal:
    pass


def test_foo():
    deal = FakeSalesDeal()
    do_something(deal)

这个测试当然会失败,因为 @typechecked 装饰器会由于不同的 class.

而引发错误

有没有办法 mock/fake FakeSalesDeal 的 class 使测试通过?

您可以使用 MagicMock 并将 spec 设置为 SalesDeal,而不是创建假的 class。

isinstance(mock, SalesDeal) 将是该模拟对象的 True & 你应该能够绕过类型检查。

from unittest.mock import MagicMock

# ...

def test_foo():
    deal = MagicMock(spec=SalesDeal)
    print(isinstance(deal, SalesDeal))
    do_something(deal)

test_foo()

这会打印:

True

& 不会抛出任何类型检查错误。

这是有效的,因为 typechecked 显式检查 Mock 传递的对象:

    if expected_type is Any or isinstance(value, Mock):
        return

代码来自 here

因此,如果您使用适当的模拟,typechecked 应该不会给您带来任何问题。

我的最终解决方案:

class FakeSalesDeal(MagicMock):
    pass