我正在尝试为使用 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/