在使用模拟函数的单元测试中,我不仅要验证参数的计数,还要验证这些参数是否符合autospec模拟函数的声明类型。
以下是示例代码:
from unittest.mock import create_autospec
def foo(a: int, b: str):
return str(a) + b
mock_foo = create_autospec(foo)
foo = mock_foo # would be patched by e.g. @patch or monkeypatch fixture
foo(1, 2)
assert foo.called
此代码测试是否正确调用了foo
。例如,这样的调用将失败:foo(1,2,3)
这包括对参数的验证,但不包括对其类型的验证。autospec或其他函数是否有方法验证传递参数的类型?这些信息在方法的签名中是可用的,所以我想我可以使用inspect
模块为自己编写这样的验证。但是,有标准的东西吗,内置的还是库?
这可以通过在mock中添加一个比较参数和注释的side_effect来解决:
from unittest.mock import create_autospec
def check_params(method):
def cp(*args, **kwargs):
for arg, typ in zip(args, method.__annotations__.values()):
assert isinstance(arg, typ)
for k, v in kwargs.values():
assert isinstance(v, method.__annotations__[k])
return cp
def foo(a: int, b: str):
return str(a) + b
mock_foo = create_autospec(foo)
mock_foo.side_effect=check_params(foo)
foo = mock_foo # would be patched by e.g. @patch or monkeypatch fixture
foo(1, 2)
assert foo.called
这将引发断言错误,因为b
应该是str
,但却是int
。
这也可以与类一起使用:从unittest.mock导入create_autospec
def check_params(method):
def cp(*args, **kwargs):
for arg, typ in zip(args, method.__annotations__.values()):
assert isinstance(arg, typ)
for k, v in kwargs.values():
assert isinstance(v, method.__annotations__[k])
return cp
class Foo:
def foo(a: int, b: str):
return str(a) + b
mock_foo = create_autospec(Foo)
mock_foo.foo.side_effect=check_params(Foo.foo)
mock_foo.foo(1, 2)
assert mock_foo.foo.called