I have the following test case for my flask app setup
class AboutViewTest(BaseTestCase):
def setUp(self):
self.url = url_for('pages_app.about',_external=True)
self.url_login_redirect = url_for('accounts_app.login')
def test_render(self):
# without login
resp = self.client.get(self.url)
self.assertRedirects(resp, self.url_login_redirect)
# after login
with self.app.test_client() as c:
login_successful = self.login(username='user1', password="123456", client=c)
self.assertTrue(login_successful)
resp = c.get(self.url)
self.assertStatus(resp, 200) # this fails
To test a view with @login_required
@pages_app.route('/about/')
@login_required
def about():
return render_template('pages/about.html')
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('accounts_app.login', next=request.url))
return f(*args, **kwargs)
return decorated_function
The second test case fails (login required) as it gets redirected to login 302 != 200
How can I test this view with to pass both the cases(with and without login)? Wht are the best practices to do this?
The best approach is probably to populate your g.user
variable as suggested in the Flask docs:
def get_user():
user = getattr(g, 'user', None)
if user is None:
user = fetch_current_user_from_database()
g.user = user
return user
Obviously, you have to define fetch_current_user_from_database()
, where you'll instantiate a user (you have a User
class, I assume) and return it. Then just call get_user()
to instantly have a user logged in when needed.
As an alternative, you can add a flag to your settings to disable login and use it in your login_required
method when testing.
For example:
from flask import current_app
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_app.config.get('LOGIN_DISABLED', False) and g.user is None:
return redirect(url_for('accounts_app.login', next=request.url))
return f(*args, **kwargs)
return decorated_function
Then in your test:
def test_render(self):
# without login
resp = self.client.get(self.url)
self.assertRedirects(resp, self.url_login_redirect)
self.app.config['LOGIN_DISABLED'] = True
resp = c.get(self.url)
self.assertStatus(resp, 200)