Open flazzarini opened 9 years ago
I managed to patch it with something like this
from flask_jwt import _jwt_required
from myflaskapp.auth import identity_handler
def mock_jwt_required(realm):
return
def mock_identity_handler(payload):
return User(123, 'foo@example.com', 'Foo', 'Bar')
@patch('flask_jwt._jwt_required', side_effect=mock_jwt_required)
@patch('myflaskapp.auth.identity_handler', side_effect=mock_identity_handler)
def test_my_authenticated_test_case(self, jwt_required_fn, identity_handler_fn):
resp = self.app.get('/protected/resource')
self.assertEquals(resp.status_code, 200, "status should be OK")
@imtheoperator, I tried to do this, but am confronted with flask_jwt's current_identity
being None
in the method under test. I can see that mock_jwt_required
is called, but mock_identity_handler
in my test is never called. In your working example:
current_identity
local proxy?Thanks!
@jsamoocha I see what you mean. I wasn't using current_identity
but I just created a new test and get the same behaviour as you:
Handler
@app.route('/api/v1/current-user', methods=['GET'])
@jwt_required()
def get_current_user():
if not current_identity:
return jsonify({"message": "Unauthorized"}), 401
# etc ...
Test using mock patches in previous comment (for identity_handler)
# patch mocks as previous comment
def test_get_current_user(self, identity_handler_fn, jwt_required_fn):
resp = self.app.get('/api/v1/current-user')
self.assertEqual(resp.status_code, 200, "Status should be 200, was %s" % resp.status_code)
Gives
AssertionError: Status should be 200, was 401
So, yes, a solution would be useful!
Ok, the following seems to be working now for a handler as mentioned above:
def mock_jwt_required(realm):
return
# test
@patch('flask_jwt._jwt_required', side_effect=mock_jwt_required)
@patch('flask_jwt._request_ctx_stack')
def test_get_user_profile(self, mock_request_ctx_stack, jwt_required_fn):
mock_request_ctx_stack.top.current_identity = User(id=MOCK_USER_ID)
# Any testing logic...
Just a small update given the the current flask version, note that:
def mock_jwt_required(realm):
return
@patch('flask_jwt._jwt_required', side_effect=mock_jwt_required)
@patch('flask_jwt._request_ctx_stack')
def test_get_user_profile(self, mock_request_ctx_stack, jwt_required_fn):
mock_request_ctx_stack.top.current_user = User(id=MOCK_USER_ID)
# Any testing logic...
For anyone who ran into a similar issue, it's better to patch the function the decorator is calling instead of trying to mock the decorator itself.
See my SO answer for details.
What I currently find a useful alternative is to separate business logic from stuff that relies on the application context, e.g.
def _get(user_id):
# whatever business logic to retrieve user data
return user_service.find(user_id)
#endpoint
@app.route('/user)
@jwt_required()
def get():
return _get(current_identity)
Now you only need to unit test _get(user_id)
without bothering about any Flask or JWT state/side effects.
I was curious to know if anyone has figured out how you would mock
jwt_required
decorator. In my unittests I would prefer not having to authenticate with my application. I thought setting theconfig
variableJWT_VERIFY
toFalse
would solve the issue, but as far as I understood the source this variable is never checked.Thanks for your help.