I'm testing a login view from a Flask application using Pytest. The login view is generated by Flask Security.
When I log in the user either by posting data to the login route or by calling the login_user method, the current_user object is set to AnonymousUser instead of returning the logged-in user.
Pytest fixtures
@pytest.fixture(scope="module")
def test_client():
flask_app = create_app(TestingConfig)
testing_client = flask_app.test_client()
ctx = flask_app.app_context()
ctx.push()
yield testing_client # this is where the testing happens!
ctx.pop()
@pytest.fixture(scope="module")
def test_db(test_client):
db.create_all()
db.session.commit()
yield db
db.drop_all()
try:
os.remove("app.db")
except e as e:
pass
Pytest test
from uuid import uuid4
import pytest
from app.models import User
from flask import current_app
from flask_login import current_user
from flask_security.utils import encrypt_password, login_user
def test_login_route(test_client, test_db):
email = "test@123.com"
password = "passwordtoencrypt"
encrypted_password = encrypt_password(password)
id = uuid4()
user = User(email=email, password=encrypted_password, id=id)
user = user.save()
test_db.session.commit()
with current_app.test_request_context():
response = test_client.post(
"/login",
data=dict(email="test@123.com", password=password),
follow_redirects=True,
)
assert current_user.email == email #Failing assert statement
And user model
class User(db.Model, UserMixin):
"""User model"""
id = db.Column(
UUIDType, unique=True, nullable=False, default=uuid4(), primary_key=True
)
first_name = db.Column(db.String(64))
last_name = db.Column(db.String(64))
email = db.Column(db.String(120), unique=True, nullable=False, index=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship(
"Role", secondary=roles_users, backref=db.backref("users", lazy="dynamic")
)
This correctly logs the user in but doesn't set the current_user object correctly.
I'm expecting my assert statement to succeed, however it throws the error E AttributeError: 'AnonymousUser' object has no attribute 'email'
You are mixing 2 concepts together in a single test - both faking a request context as well as actually initiating a request. I believe over the long term - this will really complicate your tests. The current_app.test_request_context
will push a request context, then your actual "/login" request will push another request context. That one will set current_user
but once that request context is popped (at end of request) - current_user
will be reset. A question is - why would you be testing flask-security? If you want to test that login works - then check the response.status_code - or after logging in - perform another request to one of your endpoints that required authentication.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.