Flask+Redis缓存:如何在pytest单元测试中禁用缓存?
我完全懂你遇到的糟心事——用Flask-Caching配Redis做缓存后,POST/PUT这类修改数据的单元测试总因为返回旧缓存数据失败,之前改配置的方法都没起作用对吧?这是因为缓存实例早就在应用初始化时创建好了,单纯改配置不会让新设置生效,我给你几个靠谱的解决方案:
方法一:正确禁用缓存并重新初始化缓存实例
Flask-Caching官方支持用"null"作为CACHE_TYPE来完全禁用缓存,但关键是修改配置后必须重新初始化缓存对象,不然旧的缓存实例还在偷偷工作。你可以把setUp改成这样:
def setUp(self): # 用官方指定的"null"类型禁用缓存,别用None或空字符串 app.config["CACHE_TYPE"] = "null" # 重新初始化缓存,让新配置真正生效 cache.init_app(app) self.app = app.test_client()
之前你用None或空字符串是踩了坑——Flask-Caching根本不把这些值当作禁用缓存的信号,只有"null"才是官方认可的禁用类型,再加上重新调用init_app,就能彻底关掉缓存干扰了。
方法二:每次测试前清空Redis缓存
如果有时候你需要保留缓存逻辑,只是不想让测试之间互相污染,可以在每次测试前清空Redis里的所有缓存数据。记得一定要在应用上下文里调用cache.clear():
def setUp(self): self.app = app.test_client() # 进入应用上下文,确保缓存操作能正常执行 with app.app_context(): cache.clear()
这样每次测试都会从干净的缓存状态开始,PUT/POST后的新数据就能被正确获取到了。
方法三:用pytest Fixture统一管理测试环境
更优雅的方式是用pytest的fixture来全局配置测试用的缓存设置,不用每个测试类都写重复的setUp:
import pytest from your_app_module import app, cache @pytest.fixture(scope="function") def test_client(): # 给测试环境配置禁用缓存 app.config["CACHE_TYPE"] = "null" cache.init_app(app) # 返回测试客户端供用例使用 with app.test_client() as client: yield client
然后你的测试用例可以直接用这个fixture,代码更简洁:
def test_updating_biography(test_client): response = test_client.put( "/api/1.0/biography/", data=json.dumps( dict( short="UnitTest Updated newest short", full="UnitTest Updated newest full", ) ), content_type="application/json" ) get_bio = test_client.get("/api/1.0/biography/") biodata = json.loads(get_bio.get_data().decode()) assert response.status_code == 200 assert get_bio.status_code == 200 assert biodata["biography"][0]["short"] == "UnitTest Updated newest short"
为什么之前的方法无效?
你之前修改CACHE_TYPE后没生效,核心原因是缓存实例cache在应用启动时就已经和app绑定了,后续修改app的配置不会自动更新这个缓存实例,必须调用cache.init_app(app)重新绑定,新的配置才会生效。而@cache.cached(timeout=0)没用是因为这个装饰器需要在应用上下文里运行,测试方法直接加的话没有上下文支撑,自然不会生效。
内容的提问来源于stack exchange,提问作者Juha Untinen

