繁体   English   中英

Flask、flask_login、pytest:如何设置flask_login 的current_user?

[英]Flask, flask_login, pytest: How do I set flask_login's current_user?

我正在尝试使用 pytest 对我的 Flask 应用程序进行单元测试。 对于需要来自flask_logincurrent_user信息的端点,我有以下测试用例:

def test_approval_logic():
    with app.test_client() as test_client:
        app_url_put = '/requests/process/2222'

        with app.app_context():
            user = User.query.filter_by(uid='xxxxxxx').first()
            with app.test_request_context():
                login_user(user)
                user.authenticated = True
                db.session.add(user)

                data = dict(
                    state='EXAMPLE_STATE_NAME',
                    action='approve'
                )
                resp = test_client.put(app_url_put, data=data)
                assert resp.status_code == 200

test_request_context ,我能够正确设置current_user 但是,此测试失败,因为在处理 PUT 的requests视图中,没有登录用户和 500 错误结果。 错误消息是AttributeError: 'AnonymousUserMixin' object has no attribute 'email' 有人可以解释为什么current_user消失以及我如何正确设置它吗?

以下是我在我的网站上的做法:

user = User.query.filter_by(user_id='xxxxxxx').one_or_none()
if user:
    user.authenticated = True
    db.session.add(user)
    db.session.commit()
    login_user(user)
else:
   # here I redirect to an unauthorized page, as the user wasn't found

我不知道订单是问题还是只是缺少db.session.commit() ,但我认为您需要同时完成这两项工作才能使您的 put 请求db.session.commit()

另请注意,我正在使用one_or_none()因为不应该有多个用户具有相同的user_id的可能性,只是 True 或 False 取决于是否找到了用户。

使用测试客户端发送请求

当前session未绑定到test_client ,因此请求使用新会话。

在客户端设置会话 cookie,以便 Flask 可以为请求加载相同的会话:

from flask import session

def set_session_cookie(client):
    val = app.session_interface.get_signing_serializer(app).dumps(dict(session))
    client.set_cookie('localhost', app.session_cookie_name, val)

用法:

with app.test_request_context():
    login_user(user)
    user.authenticated = True
    db.session.add(user)

    data = dict(
        state='EXAMPLE_STATE_NAME',
        action='approve'
    )
    set_session_cookie(test_client)  # Add this
    resp = test_client.put(app_url_put, data=data)

使用测试请求上下文而不分派请求

https://flask.palletsprojects.com/en/2.0.x/api/#flask.Flask.test_request_context

这在测试期间非常有用,您可能希望运行使用请求数据的函数,而无需分派完整请求。

用法:

data = dict(
    state='EXAMPLE_STATE_NAME',
    action='approve'
)
with app.test_request_context(data=data):  # Pass data here
    login_user(user)
    user.authenticated = True
    db.session.add(user)

    requests_process(2222)  # Call function for '/requests/process/2222' directly

我的猜测是您的 PUT 请求中没有传递会话 cookie。

这是我在测试期间如何记录用户的示例(我个人使用unittest而不是pytest ,所以我将代码减少到严格的最小值,但如果您想要一个完整的unittest示例,请告诉我)

from whereyourappisdefined import application
from models import User
from flask_login import login_user

# Specific route to log an user during tests
@application.route('/auto_login/<user_id>')
def auto_login(user_id):
    user = User.query.filter(User.id == user_id).first()
    login_user(user)
    return "ok"

def yourtest():
    application.config['TESTING'] = True # see my side note
    test_client = application.test_client()
    response = test_client.get(f"/auto_login/1")

    app_url_put = '/requests/process/2222'
    data = dict(
        state='EXAMPLE_STATE_NAME',
        action='approve'
    )
    r = test_client.put(app_url_put, data=data)
    

在文档中我们可以阅读: https : //werkzeug.palletsprojects.com/en/2.0.x/test/#werkzeug.test.Client

use_cookies 参数指示是否应为后续请求存储和发送 cookie。 默认情况下这是 True 但传递 False 将禁用此行为。

因此,在第一个请求GET /auto_login/1 期间,应用程序将收到一个会话 cookie 并保留它以供进一步的 HTTP 请求使用。

边注:

在设置期间,TESTING 配置标志被激活。 这样做是在请求处理期间禁用错误捕获,以便在对应用程序执行测试请求时获得更好的错误报告。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM