Search code examples
pythonpython-3.xunit-testingflaskflask-testing

How do I mock a flask decorator @login_required for my unit tests?


I am working on an application which requires a few unit tests to be written. I wanted to ask how can I mock a decorator '@login_required' in my unit tests? here is a function which has the @login_required function in app.py

@app.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
    global application_inst
    if request.method == 'POST':
        print("Setting changed")

    return render_template('settings.html', user=session['user'], application=application_inst)

and here is my unit testcase in test_app.py

class MyTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app(db)
        self.app.config['TESTING'] = True
        self.app.config['LOGIN_DISABLED'] = True
        self.app.config['WTF_CSRF_ENABLED'] = False
        self.app.config['DEBUG'] = True
        self.client = self.app.test_client(self)

    def test_settings_passed(self):
        with self.client:
            response = self.client.get('/settings', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

Since there was no way for me to get the test passed ie. status_code = 200 as it expects 404. I have tried everything available on the internet and it didn't solve my issue. Hence I wanted to try mocking the decorator. How can I do it? Please help me as I am stuck in this problem since long.


Solution

  • I assume you're using the decorator from flask_login.

    It's not really possible to post-hoc mock a decorator, because its decoration has already taken place. That said, you can look at what the decorator does in order to find out how to mock it.

    As you can see in the source, there's a bunch of cases where the login won't be enforced:

    if request.method in EXEMPT_METHODS:
        return func(*args, **kwargs)
    elif current_app.config.get('LOGIN_DISABLED'):
        return func(*args, **kwargs)
    elif not current_user.is_authenticated:
        return current_app.login_manager.unauthorized()
    return func(*args, **kwargs)
    

    You can:

    • mock EXEMPT_METHODS to include GET and POST.
    • mock the LOGIN_DISABLED config value
    • mock current_user.is_authenticated