python - 在 Flask 单元测试中覆盖 flask.g

标签 python unit-testing flask flask-login

我正在尝试为使用 OpenID 进行身份验证的 flask 应用程序编写一些单元测试。由于似乎无法通过 OpenID 登录测试客户端(我问了这个问题但没有收到任何回复:Flask OpenID unittest),我想在我的测试中覆盖 g.user,所以我尝试了来自 http://flask.pocoo.org/docs/testing/#faking-resources-and-context 的代码片段并且按预期工作。

不幸的是,当使用 flask-login 时,g.user 在设置的 before_request 包装器中被覆盖

g.user = current_user

current_user 是匿名的,所以我的测试用例坏了。一种解决方法是仅在测试模式下执行 before_request 包装器代码,但您需要在生产代码中添加特定于测试的逻辑似乎很蹩脚。我也试过弄乱请求上下文,但 g.user 最终还是被覆盖了。任何解决这个问题的干净方法的想法?

最佳答案

官方文档有an example in "Faking Resources and Context" :

您首先需要确保 g.user 仅在其不存在时才被设置。您可以使用 getattr 执行此操作。这是一个稍微修改过的示例:

@APP.before_request
def set_user():
    user = getattr(g, 'user', None)
    if user is None:
        g.user = concrete_implementation()
    return user

通过使用 getattr,我们给了自己在测试期间“注入(inject)”某些东西的机会。如果我们不这样做,我们将在单元测试注入(inject)值后用具体实现再次覆盖变量。

接下来我们要做的是挂接到 appcontext_pushed 事件,并使用可测试的值设置 g.user 值。这发生在之前 before_request 钩子(Hook)。所以当 that 被调用时 getattr 将返回我们的测试值并跳过具体实现:

from contextlib import contextmanager
from flask import appcontext_pushed, g

@contextmanager
def user_set(app, user):
    def handler(sender, **kwargs):
        g.user = user
    with appcontext_pushed.connected_to(handler, app):
        yield

有了这个小 helper ,我们可以在需要使用可测试值时注入(inject)一些东西:

def test_user_me():
    with user_set(app, 'our-testable-user'):
        c = app.test_client()
        resp = c.get('/protected-resource')
        assert resp.data == '...'

关于python - 在 Flask 单元测试中覆盖 flask.g,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23164993/

相关文章:

python - scikit learn 插补 NaN 以外的值

python - scipy 的 curve_fit 函数的维度问题

unit-testing - 如何使用 Mockito 和 JUnit 在 Spring boot 中测试 POST 方法

ajax - 如何让selenium等待ajax响应?

python - 条件 Flask-WTF 表单字段

python - 列表理解中的每个项目是否在构建列表时得到解析?

python - asyncio.run 运行时错误 : Event loop is closed

c# - 使用属性 CharacterSet 的值模拟 HttpWebResponse

python-2.7 - flask 登录可重复使用的 cookies

python - Flask 无法识别两个 URL 参数