PyTest中@singledispatch与@typechecked未触发预期NotImplementedError问题
解决
test_score_not_implemented_error() 测试用例通过问题 问题根源分析
@typechecked装饰器冲突:该装饰器会在函数执行前强制校验参数类型,不符合要求的参数会直接抛出TypeCheckError,根本无法触发我们自定义的NotImplementedError逻辑,导致测试失败。- 移除
@typechecked后的TypeError:说明多态分支的匹配逻辑存在漏洞,非目标类型参数错误进入了某个分支,触发了不兼容的运算(比如对字符串做加减/求和操作)。
解决方案:分层实现多态与异常转换
通过拆分函数为内层多态实现和外层异常转换层,既保留类型校验的安全性,又能正确触发自定义异常。
代码示例
from functools import singledispatch from typeguard import typechecked, TypeCheckError from typing import List, Any # 内层:负责多态分支的类型校验与业务逻辑 @singledispatch def _score(count_neg, count_pos): raise NotImplementedError("Unsupported parameter types") # 注册 Tuple[int, int] 类型分支 @_score.register @typechecked def _(count_neg: int, count_pos: int): total = count_pos + count_neg return (count_pos - count_neg) / total if total != 0 else 0 # 注册 Tuple[List[int], List[int]] 类型分支 @_score.register @typechecked def _(count_neg: List[int], count_pos: List[int]): total_neg = sum(count_neg) total_pos = sum(count_pos) total = total_pos + total_neg return (total_pos - total_neg) / total if total != 0 else 0 # 外层:捕获类型校验异常,转换为要求的 NotImplementedError def score(count_neg: Any, count_pos: Any): try: return _score(count_neg, count_pos) except TypeCheckError: raise NotImplementedError("Unsupported parameter types") from None
逻辑说明
- 内层
_score:通过@singledispatch实现多态,每个分支用@typechecked确保参数类型合法,避免运算时出现TypeError。 - 外层
score:作为对外接口,捕获内层抛出的TypeCheckError(即参数不符合任何注册分支的类型要求),转换为测试用例要求的NotImplementedError。
测试用例验证
def test_score_not_implemented_error(): # 测试字符串类型参数 try: score("invalid", "invalid") assert False, "Expected NotImplementedError" except NotImplementedError: pass # 测试混合类型参数 try: score(1, [2]) assert False, "Expected NotImplementedError" except NotImplementedError: pass # 测试合法类型(验证正常逻辑不被影响) assert score(3, 7) == 0.4 assert score([1,2], [3,4]) == (7-3)/(7+3) == 0.4
内容的提问来源于stack exchange,提问作者DanielBell99
相关产品推荐
相关产品推荐

