如何用pytest模拟joblib缓存,强制调用原函数执行单元测试?
pytest测试joblib缓存函数:跳过缓存调用原函数的几种方法
针对你提到的场景,有几种实用的方法可以确保测试时跳过缓存、调用原函数,下面逐一说明:
方法一:直接调用被装饰的原函数
joblib的装饰器会把原函数保存在被装饰函数的__wrapped__属性中,测试时直接调用这个属性对应的函数即可绕开缓存,最简单直接:
def test_func(): # 直接调用未被缓存的原函数逻辑 assert func.__wrapped__(2) == 4
这种方法不需要修改原代码,也不需要额外依赖,适合快速测试单个函数。
方法二:临时禁用缓存
如果需要保持函数调用方式不变(还是用func(2)),可以临时修改Memory对象的配置来禁用缓存:
方式1:修改Memory实例的缓存路径
def test_func_disable_cache(): # 保存原缓存路径,测试后恢复 original_cachedir = memory.cachedir memory.cachedir = None # 设置为None会禁用缓存 try: assert func(2) == 4 finally: memory.cachedir = original_cachedir
方式2:用monkeypatch替换Memory实例
利用pytest的monkeypatch fixture,临时替换全局的memory对象为不缓存的实例:
def test_func_with_monkeypatch(monkeypatch): # 创建一个不缓存的Memory实例替换原对象 no_cache_memory = Memory(location=None, verbose=0) monkeypatch.setattr("__main__.memory", no_cache_memory) # 此时调用func会使用新的无缓存装饰器 assert func(2) == 4
方法三:模拟joblib.Memory对象(适用场景)
如果你的代码中Memory的创建逻辑复杂,或者想彻底隔离缓存(比如避免生成临时缓存文件),模拟Memory是完全可行的。通过mock让Memory.cache直接返回原函数,相当于跳过装饰过程:
from unittest.mock import patch from importlib import reload import __main__ as module # 替换成你的实际模块名 def test_func_mock_memory(): with patch("joblib.Memory") as mock_memory_cls: # 让mock的cache方法不做任何装饰,直接返回原函数 mock_memory = mock_memory_cls.return_value mock_memory.cache = lambda func: func # 重新加载模块,使mock生效(因为原模块已经执行过装饰) reload(module) # 此时调用的是未被缓存的func assert module.func(2) == 4
这种方式适合需要完全隔离外部依赖的测试场景,确保测试不受缓存状态影响。
内容的提问来源于stack exchange,提问作者Andi
相关产品推荐
相关产品推荐

