简体   繁体   中英

How to get current_user from Flask Login to return a logged in user when using Pytest?

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.

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