如何确保mock方法的return_value与被mock方法的类型提示兼容
单元测试mock返回值类型不匹配的检测方案
原生能力说明
原生unittest.mock本身未内置基于类型提示的返回值校验能力,默认不会检测你设置的return_value和方法声明的返回类型是否兼容,所以才会出现示例中测试通过但不符合实际运行场景的问题。
可行的解决方法
- 方案1:结合静态类型检查工具(推荐)
常用的Python静态类型检查工具如mypy、pyright都可以识别autospec参数生成的Mock对象类型,你在给Mock方法的return_value赋值时,如果类型和原方法的返回注解不匹配,静态检查工具会直接抛出错误。
你提供的示例代码用mypy扫描时,会直接报如下错误:
这个方案不需要修改任何运行时测试代码,只需要把静态类型检查加入测试流水线即可,成本最低。error: Incompatible types in assignment (expression has type "str", variable has type "datetime") [assignment] - 方案2:自定义带类型校验的Mock类
如果你需要在测试运行时就拦截这类错误,可以自己继承unittest.mock.Mock实现带类型校验的Mock类,在设置return_value时自动读取原方法的类型注解做校验,示例实现如下:
使用时在import inspect from unittest.mock import Mock class TypeCheckedMock(Mock): def __setattr__(self, name, value): if name == "return_value" and hasattr(self, "_spec_class") and self._spec_class is not None: # 获取原方法的签名和返回类型注解 sig = inspect.signature(self._spec_class) return_type = sig.return_annotation # 存在明确返回注解时做校验 if return_type != inspect.Signature.empty and not isinstance(value, return_type): raise TypeError(f"返回值类型不匹配:期望{return_type.__name__},实际传入{type(value).__name__}") super().__setattr__(name, value)@patch装饰器中指定new_callable=TypeCheckedMock即可,当你给return_value赋值错误类型时,测试运行会直接抛出异常。 - 方案3:引入运行时类型检查库
可以用typeguard、pydantic这类运行时类型校验库,给待测方法加上类型校验装饰器,不管是真实实例还是Mock实例调用,只要返回值不符合类型注解就会直接报错,这种方式可以同时覆盖真实代码和测试代码的类型问题,适合对类型正确性要求高的项目。
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

