考虑MagicMock时MyPy如何工作

问题描述 投票:0回答:1

我正在考虑在我的测试中启用与生产代码中相同的

mypy
规则。我开始在
mypy
操场上做一些修补,发现一些我不太明白
mypy
MagicMock
如何一起玩的事情。假设我有以下课程:

class A:
    def method(self, variable: int) -> None:
        print("Hey!")

现在,我想在另一个测试中创建该类的模拟,所以我会这样做:

mock = MagicMock(spec_set=A)

因为如果我尝试做类似的事情,我已经使用了

spec_set

mock.not_existing.return_value = "Meh"

然后我会得到一个运行时错误,但令人惊讶的是(?)我不会从

mypy
得到任何错误。这让我觉得也许 mypy 只是忽略了与
MagicMock
相关的所有内容。然后我尝试了类似的事情:

def function(some: A) -> None:
    print(some)
    
# no mypy error either
function(mock)

再次,它不会触发任何

mypy
错误,我猜这是预期的行为,因为该模拟正在嘲笑
A
。尽管如此,如果你将其更改为:

class B:
    def method_2(self, variable: int) -> None:
        print("Hey!")
        

mock_2 = MagicMock(spec_set=B)
function(mock_2)

然后,也没有

mypy
错误。我还尝试了以下方法:

mock: A = MagicMock(spec_set=A)
mock.not_existing.something() # runtime and mypy error
mock.method.return_value = 1 # mypy error due to return_value not existing

那么,有什么办法可以改变这种行为呢?如果没有这个,我不确定在我的测试中添加

mypy
是否有意义,因为我猜我会得到假阴性。

作为问题的奖励部分,我也想到了这一点:

mock.method.return_value = "Meh"

这不会触发任何错误(运行时或来自

mypy
)。理想情况下,它应该抛出两者,因为我违反了规范(所以我猜
spec_set
应该对此做点什么),而且因为我没有返回
None
,正如类型提示所暗示的那样。

在这里您可以在

mypy
游乐场

测试相同的示例
python unit-testing python-typing mypy magicmock
1个回答
0
投票

来自typeshed

# We subclass with "Any" because mocks are explicitly designed to stand in for other types,
# something that can't be expressed with our static type system.
class NonCallableMock(Base, Any):

类型检查器查看此存根文件,将

Any
视为
NonCallableMock
的超类,并有效禁用此类所有实例的大多数类型检查。其中包括
MagicMock
的实例,它是
NonCallableMock
的后代。

© www.soinside.com 2019 - 2024. All rights reserved.