[英]Flask, flask_login, pytest: How do I set flask_login's current_user?
我正在尝试使用 pytest 对我的 Flask 应用程序进行单元测试。 对于需要来自flask_login
的current_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.