簡體   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