Mock authentication decorator in unittesting
Here an example which can help you. Structure of files below.
app.py
from flask import Flaskfrom third_part.example import validate_tokenapp = Flask(__name__)@app.route('/')@validate_token()def index(): return 'hi'if __name__ == '__main__': app.run(debug=True)
/third_part/example.py
from functools import wrapsdef validate_token(): def validate(func): @wraps(func) def wrapper(*args, **kwargs): raise Exception('Token error. Just for example') return func(*args, **kwargs) return wrapper return validate
tests.py:
from app import appapp.testing = Truedef test_index(): with app.test_client() as client: client.get('/')
Run our tests.py
(just make sure that decorator works):
@wraps(func) def wrapper(*args, **kwargs):> raise Exception('Token error. Just for example')E Exception: Token error. Just for example
First way how to skip decorator(using patch
). tests.py:
from functools import wrapsfrom mock import patchdef mock_decorator(): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): return f(*args, **kwargs) return decorated_function return decoratorpatch('third_part.example.validate_token', mock_decorator).start()# !important thing - import of app after patch()from app import appapp.testing = Truedef test_index(): with app.test_client() as client: client.get('/')
Second way(without patch
). tests.py:
from functools import wrapsfrom third_part import exampledef mock_decorator(): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): return f(*args, **kwargs) return decorated_function return decorator# !important thing - import of app after replaceexample.validate_token = mock_decoratorfrom app import appapp.testing = Truedef test_index(): with app.test_client() as client: client.get('/')
Run our test.py(in 2 ways):
tests.py . [100%]=========================== 1 passed in 0.09 seconds ===========================
Summarize. As you can see, very important thing is when you replace the function. By the way, you trying to patch validate_token
of views
module, but not third_part.module
Hope this helps.