【问题标题】:Overriding flask.g in flask unit test在烧瓶单元测试中覆盖 flask.g
【发布时间】:2014-04-19 02:10:50
【问题描述】:

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

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

g.user = current_user

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

【问题讨论】:

    标签: python unit-testing flask flask-login


    【解决方案1】:

    官方文档有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,我们让自己有机会在测试期间“注入”一些东西。如果我们不这样做,我们将在单元测试注入值之后用具体实现再次覆盖该变量。

    接下来我们要做的是挂钩appcontext_pushed 事件并将g.user 值设置为可测试的值。这发生在before_request 钩子之前。因此,当 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
    

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

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

    【讨论】:

      【解决方案2】:

      基于另一个问题in a Flask unit-test, how can I mock objects on the request-global `g` object? 对我有用的是:

      在我的应用程序中,我将 before_request 中包含的登录逻辑重构为一个单独的函数。然后,我在我的测试中修补了该函数,以便它返回我想要用于一堆测试的特定用户。 before_request 仍然与测试一起运行,但通过修补它调用的函数,我现在可以避免实际的登录过程。

      我不确定这是不是最干净的方法,但我认为这比在 before_request 中添加仅测试逻辑要好;这只是一个重构。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-15
        • 2020-09-08
        • 2021-09-07
        • 2017-12-07
        • 2018-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多