cachetools cachedmethod 让 autospec 报 missing a required argument
cachetools 7.2.2、7.2.3 的 cachedmethod 类访问包装会影响 autospec 调用,7.2.4 已修复。不要给实例补传 self;另行测试真实缓存与调用接口。
升级 cachetools 后,真实对象的方法仍能调用,unittest.mock.create_autospec 生成的对象却在传入一个参数时提示:
TypeError: missing a required argument: 'key'
如果该方法使用 @cachedmethod,并且环境是 cachetools 7.2.2 或 7.2.3,应先核对装饰器描述符与 autospec 的配合。这项回归已在正式 7.2.4 修复,当前版本要求 Python 3.10 及以上。
业务方法只有一个参数,为何 mock 还在等参数
7.2.2 为支持类访问及 super() 调用,调整了 cachedmethod 的描述符。通过类获取方法时会得到带接收者的函数,而 autospec 对这个对象的签名推断没有按正常实例方法去掉接收者,于是已提供的 key 被算到前一个位置。
这不意味着缓存中的 key 丢失,也不要求业务调用者把 self 再传一次。给实例 mock 补一个假的 self,会让测试接口与实际代码分离。
下面是用于核对调用契约的简化示例,缓存行为本身应另用真实对象测试:
from unittest.mock import create_autospec
from cachetools import cachedmethod
class Service:
def __init__(self):
self.cache = {}
@cachedmethod(lambda self: self.cache)
def cached(self, key):
return key
service = create_autospec(Service, instance=True)
service.cached.return_value = "value"
result = service.cached("key")
service.cached.assert_called_once_with("key")
7.2.4 的类访问包装对象不再是普通函数,恢复了这一 autospec 调用路径。升级后要重新创建 mock,并在测试使用的解释器里确认依赖已经切换;另一个终端里装了新包,不会改变正在运行的测试进程。
保留其他方法的签名检查
这项修复恢复可调用性,不保证装饰方法在 mock 中拥有与未装饰函数完全相同的严格参数检查。7.2.4 的包装调用采用可变参数,因此不能只凭错误调用不再报错,就断言所有参数都已验证。
若测试必须精确限制服务接口,可以对独立的接口类或协议建立 autospec,把缓存作为具体实现细节;同时用真实 Service 检查缓存命中、不同 key 和失效行为。不要为绕过一个装饰方法的问题,把全套测试都换成不带 spec 的 Mock。
暂时锁定旧依赖需要核对项目为何升级:7.2.2 还包含 super() 等其他修订,整体回退可能恢复另一项已解决的问题。已有 7.2.4 的正式修复时,应优先评估它与项目 Python 及依赖约束的兼容性。
复核时把 mock 调用测试和真实缓存测试分开看:前者检查调用与返回值约定,后者才证明结果确实来自预期缓存。给 mock 设置了 return_value,无法证明真实缓存策略正确。


