You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:06:14