Skip to content Skip to sidebar Skip to footer

How To Mock `current_user` In Flask Templates?

I want to mock flask-login's current_user under the template rendering. This function return the current logged user. Right now I'm mocking the AnnonymousUserMixin from flask-logi

Solution 1:

Okay. I found the answer.

flask-login will ask you to initialize a LoginManager instance with login_manager.init_app(your_app). When you do this it add the current_user to your app contexts processors. This happens at flask_login.utils._user_context_processor function, which is defined as

def_user_context_processor():
    returndict(current_user=_get_user())

Here _get_user is defined at the same module. What I do to mock current_user is mock _get_user at flask_login.utils.

Here is a working example of how it can be done. I am printing the response content so people can see the result differing. A real test would not instantiate Test class by hand and should use unittest.main or something appropriated.

from flask import Flask, render_template_string as render_string
from flask_login import LoginManager, UserMixin

app = Flask(__name__)
loginmgr = LoginManager(app)
loginmgr.init_app(app)


classUser(UserMixin):
    pass@loginmgr.user_loaderdefload_user(user_id):
    return User.get(user_id)


@app.route('/')defindex():
    return render_string('Hello, {{ current_user | safe }}')


if __name__ == '__main__':
    import unittest
    from unittest import mock

    classTest:
        deftest(self):
            client = app.test_client()
            response = client.get('/')
            data = response.data.decode('utf-8')
            print(data)

        @mock.patch('flask_login.utils._get_user')deftest_current_user(self, current_user):
            user = mock.MagicMock() 
            user.__repr__ = lambda self: 'Mr Mocked'
            current_user.return_value = user
            client = app.test_client()
            response = client.get('/')
            data = response.data.decode('utf-8')
            print(data)


    t = Test()
    t.test()
    t.test_current_user()

Here is the output of it:

Hello, <flask_login.mixins.AnonymousUserMixin object at 0x7f9d5ddaaf60>
Hello, Mr Mocked

Regards,

Solution 2:

I found this tutorial interesting in the section The Test.

It says this:

current_user needs to be accessed within the context of a request (it is a thread-local object, just like flask.request). When self.client.post completes the request and every thread-local object is torn down. We need to preserve the request context so we can test our integration with Flask-Login. Fortunately, Flask’s test_client is a context manager, which means that we can use it in a with a statement and it will keep the context around as long as we need it:

So in simple words, you can log in your user via post request and the current_user object will be available and then you can test everything you want in the code.

Here is an example:

with self.client:
    response = self.client.post(url_for('users.login'),
                                data={'email': 'joe@joes.com', 'password': '12345'})

    self.assert_redirects(response, url_for('index'))
    self.assertTrue(current_user.name == 'Joe')
    self.assertFalse(current_user.is_anonymous())

Post a Comment for "How To Mock `current_user` In Flask Templates?"