This is the function I wish to test
@jwt_required
def get_all_projects(self):
# implementation not included here
I call the function from a pytest class
def test_get_all_projects(db_session):
all_projects = ProjectController.get_all_projects()
with the db_session
fixture
@pytest.fixture(scope='function')
def db_session(db, request):
"""Creates a new database session for a test."""
engine = create_engine(
DefaultConfig.SQLALCHEMY_DATABASE_URI,
connect_args={"options": "-c timezone=utc"})
DbSession = sessionmaker(bind=engine)
session = DbSession()
connection = engine.connect()
transaction = connection.begin()
options = dict(bind=connection, binds={})
session = db.create_scoped_session(options=options)
db.session = session
yield session
transaction.rollback()
connection.close()
session.remove()
This result in the error
> raise NoAuthorizationError("Missing {} Header".format(header_name))
E flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header
../../.virtualenvs/my-app/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py:132: NoAuthorizationError
create_access_token
I still get the same result when I call create_access_token
in the fixture above
db.session = session
session._test_access_token = create_access_token(identity='pytest')
yield session
How can I fake JWT tokens during testing with pytest
?
Next try to fetch the list of users. To do that, change the endpoint to /user and then in the headers section, add a field as x-access-token and add the JWT token in the value and click on Send. You will get the list of users as JSON. So, this is how you can perform authentication with JWT in Flask.
Flask-JWT-Extended not only adds support for using JSON Web Tokens (JWT) to Flask for protecting routes, but also many helpful (and optional) features built in to make working with JSON Web Tokens easier. These include: Automatic user loading ( current_user ).
This token will identify us as logged in. The JSON contains the token. Note it down. Next try to fetch the list of users. To do that, change the endpoint to /user and then in the headers section, add a field as x-access-token and add the JWT token in the value and click on Send.
Even when checking code coverage, arguments can still be passed to pytest: This article provides a guide for testing Flask applications, focusing on: Patrick is a software engineer from the San Francisco Bay Area with experience in C++, Python, and JavaScript. His favorite areas of teaching are Vue and Flask.
One option for faking JWT tokens during unit testing is to patch jwt_required. More specifically patch the underlying function verify_jwt_in_request
. This mocks the decorator and removes the need to create authorization tokens for the test.
from unittest.mock import patch
@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
def test_get_all_projects(mock_jwt_required):
# ...
@jwt_required
only works in the context of a Flask request. You can send in the access token using the flask test client with the headers name option:
def test_foo():
test_client = app.test_client()
access_token = create_access_token('testuser')
headers = {
'Authorization': 'Bearer {}'.format(access_token)
}
response = test_client.get('/foo', headers=headers)
# Rest of test code here
Optionally, you could unwrap the decorated method by using the __wrapped__
property. In your case, it would look like:
method_response = get_all_projects.__wrapped__()
Note that any calls to the flask-jwt-extended helper functions in your endpoint (such as get_jwt_identity()
, current_user
, etc). would not work this way, as they require a flask request context. You could get around this by mocking the flask-jwt-extended functions used inside the function, but that may be harder to maintain as the application grows and changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With