如何在请求上下文外mock flask.g和Flask-RESTful.request
问题原因
你遇到的Working outside of request context报错,本质是因为flask_restful.request是 Flask 提供的全局请求代理对象,只要访问该对象的任意属性,就会自动触发活跃请求上下文检查,即使你尝试Mock该对象,只要触发属性访问就会先执行检查逻辑,因此会抛出上下文不存在的错误。
解决方案
这里提供两种可行方案:
方案一:使用Flask测试请求上下文(推荐)
该方案更贴近代码实际运行场景,无需额外Mock,测试结果可信度更高:
import pytest from flask import Flask from core.helpers import auth def test_authenticate(): # 初始化最小可用的Flask应用实例 app = Flask(__name__) # 通过测试请求上下文模拟带指定头的HTTP请求 with app.test_request_context(headers={"by-pass": "internal-bypass-key"}): @auth.Auth.authenticate def test_func(*args, **kwargs): return "hello" # 执行校验逻辑 assert test_func() == "hello" from flask import g assert g.user == "by_pass"
如果你需要测试bypass不生效的场景,只需要修改test_request_context传入的headers参数即可。
方案二:直接Mock模块内的导入引用
如果你不想引入Flask应用实例,可以直接替换auth模块内已经导入的request和g对象,完全覆盖原代理对象的逻辑:
import pytest from core.helpers import auth def test_authenticate(mocker): # Mock auth模块内导入的request对象 mock_request = mocker.patch("core.helpers.auth.request") mock_request.headers.get.return_value = "internal-bypass-key" # Mock auth模块内导入的g对象 mock_g = mocker.patch("core.helpers.auth.g") @auth.Auth.authenticate def test_func(*args, **kwargs): return "hello" assert test_func() == "hello" assert mock_g.user == "by_pass" # 注意:assert_called_once_with本身是断言方法,不需要额外加assert前缀 mock_request.headers.get.assert_called_once_with("by-pass")
该方案需要注意Mock的路径必须是业务代码实际导入的路径,也就是core.helpers.auth.request而非flask_restful.request,否则Mock不会生效。
内容的提问来源于stack exchange,提问作者rajeshagashe
相关产品推荐
相关产品推荐

