为何pytest中的monkeypatch打桩未生效?
问题原因
你遇到的monkeypatch不生效,核心原因是模块导入的引用机制:
在app/auth/views.py中,你用from app.auth.utils import get_user把get_user函数直接导入到了views模块的命名空间里。这意味着视图函数me_get调用的是views模块本地的get_user引用,而不是utils模块里的原函数。你现在monkeypatch的是app.auth.utils.get_user,自然不会影响到视图里的调用。
解决方法
有两种可行的修复方式,选一种就行:
方式一:修改monkeypatch的目标路径
直接针对views模块里的get_user引用做替换,测试代码改成这样:
def test_smoke_me_api(self, monkeypatch): # 重点:修改目标路径为视图模块里的get_user monkeypatch.setattr("app.auth.views.get_user", mock_get_user) re = self.c.get("/me/") # 可添加断言验证mock生效 assert re.json()["email"] == "test@test.org"
方式二:调整视图里的导入方式
如果不想每次都改monkeypatch路径,可以修改app/auth/views.py的导入方式,让它始终从utils模块引用函数:
# 把原来的from import改成导入整个模块 import app.auth.utils @router.get("/") async def me_get(sub: str = Security(auth.verify)) -> dict: # 调用时通过模块访问函数 return app.auth.utils.get_user(sub)
这时候你原来的monkeypatch代码(monkeypatch.setattr("app.auth.utils.get_user", mock_get_user))就能正常生效了。
额外提示
- 不要在
setup_class里用monkeypatch,因为setup_class是类级别的初始化,pytest的fixture(比如monkeypatch)无法直接注入到类的setup方法里,放在测试方法里使用是正确的做法。 - 如果
auth.verify依赖需要mock才能让/me/接口正常访问,记得也要处理这个依赖(比如用FastAPI的依赖覆盖或额外monkeypatch),否则测试可能会因鉴权失败无法正常运行。
内容的提问来源于stack exchange,提问作者creyD
相关产品推荐
相关产品推荐

