如何将标题添加到烧瓶test_request_context?

时间:2019-12-18 16:17:08

标签: python flask pytest

我有一个测试装置,可以在我的烧瓶应用中创建测试客户端:

@pytest.fixture(scope='session') 
def test_client():
    """ Create the application and the test client. 
    """
    print('----------Setup test client----------')
    app = create_app(config_class=config.TestConfig)
    testing_client = app.test_client()

    ctx = app.test_request_context() 
    ctx.push()
    yield testing_client # this is where the testing happens
    print('-------Teardown test client--------')
    ctx.pop()

我想在此测试请求上下文中添加“ User-Agent”的标头,因为在我的应用程序中,我检查用户的浏览器。我通过

在我的应用中检索浏览器名称
user_agent = flask.request.user_agent.browser

如果我使用上面的测试客户端,此行将返回None。虽然我可以在单个测试中的单个请求中成功设置“ User-Agent”标头,例如:

user_agent_str = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'

response = test_client.get('/some_flask_route',
        environ_base={'HTTP_USER_AGENT': user_agent_str},
        follow_redirects=True)

这样做之后: flask.request.user_agent.browser 按预期返回“ chrome”。

但是,这是非常多余的,因为它要求我将environ_base代码行插入许多测试的每一个中。

预期行为

我希望在测试夹具中创建测试请求上下文时可以设置标头,例如:

user_agent_str = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'

@pytest.fixture(scope='session') 
def test_client():
    """ Create the application and the test client. 
    """
    print('----------Setup test client----------')
    app = create_app(config_class=config.TestConfig)
    testing_client = app.test_client()
    ctx = app.test_request_context(environ_base={'HTTP_USER_AGENT': user_agent_str}) 
    ctx.push()
    yield testing_client # this is where the testing happens
    print('-------Teardown test client--------')
    ctx.pop()

这将为所有请求设置环境,而无需在我的每个请求中都设置environ_base。

实际行为

虽然将environ_base添加到test_request_context()不会破坏固定装置,但不会设置'User-Agent'标头和

flask.request.user_agent.browser

不返回任何内容。

环境

  • Python版本:3.7.3
  • 烧瓶版本:1.1.1
  • Werkzeug版本:0.15.4

我已经尝试过以下问题中建议的解决方案:Setting (mocking) request headers for Flask app unit test

,但似乎没有任何改变。我只是在尚未部署的本地主机上运行Flask服务器,即实际上只是:

app = Flask(__name__)
app.run(host='127.0.0.1',port=5000,debug=True)

2 个答案:

答案 0 :(得分:1)

测试客户端具有outlier <- structure(list(cases = c("S35718:10.63,S35585:6.75,S35708:7.28,S36617:12.23", "S35718:10.63"), counts = c("6.75,7.28,10.63,12.23,6.17,4.09,3.95,5.00", "10.63")), class = "data.frame", row.names = c(NA, -2L)) 属性,该属性设置在构建每个请求时要开始的默认环境。

environ_base

要更好地控制传递给每个请求的内容,可以将c = app.test_client() c.environ_base["HTTP_USER_AGENT"] = "Firefox/71.0" 子类化以覆盖FlaskClient

open

类似地,class CustomClient(FlaskClient): def open(self, *args, **kwargs): headers = kwargs.setdefault("headers", {}) headers.setdefault("User-Agent", "Firefox/71.0") return super().open(*args, **kwargs) app.test_client_class = CustomClient c = app.test_client() assert c.get("/browser") == "firefox" 可以被子类化以覆盖Flask

test_request_context

请勿为所有测试全局推送测试请求上下文。应该为每个请求创建一个新的上下文,并且在使用class CustomFlask(Flask): def test_request_context(self, *args, **kwargs): headers = kwargs.setdefault("headers", {}) headers.setdefault("User-Agent", "Firefox/71.0") return super().test_request_context(*args, **kwargs) app = CustomFlask() with app.test_request_client(): assert browser() == "firefox" 发出测试请求时将自动处理该上下文。在会话固定装置中按一下将不会达到您想要的效果。在大多数情况下,您应该在client上使用test_client


重新考虑为什么首先要依赖用户代理。将应用程序行为基于用户代理通常是错误的设计,因为浏览器会误报它们,并且功能会随着时间而改变。

答案 1 :(得分:0)

您可以在初始化时添加标题

示例:

from flask import request

request_ctx = app.test_request_context(
    headers={'Authorization': 'Bearer XXXXX')}
)

request_ctx.push()

request.headers
# Output: EnvironHeaders([('Host', 'localhost'), ('Authorization', 'Bearer XXXXX')])