I wanted to mock validate_token
decorator while writing unit test for one of view
#views.py
from third_part.module import vaidate_token
from setting import config
class myViews:
@validate_token([config['issuer'], config['secret_key']])
def get_data():
#Do stuff
return json.loads(data)
Here validate_token is a thirtd_party module to authorize request and the token is issued by third party so I don't want execute validate_token decorator for my tests
below are my sample test code.
test_views.py
@patch('views.validate_token', lambda x: x)
def test_get_data(self):
endpoint = '/app/get_data'
res = self.client.get(endpoint)
assert res.status_code==200
I tried to mock while running tests
But its not working as expected, , its giving 401 error.
how can I mock/patch decorator for tests anything am missing here
Thanks in advance.
Accessing the same attribute will always return the same mock. Mocks record how you use them, allowing you to make assertions about what your code has done to them. MagicMock is a subclass of Mock with all the magic methods pre-created and ready to use.
unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.
PropertyMock : A mock intended to be used as a property, or other descriptor, on a class. PropertyMock provides __get__ and __set__ methods so you can specify a return value when it is fetched.
Here an example which can help you. Structure of files below.
app.py
from flask import Flask
from third_part.example import validate_token
app = Flask(__name__)
@app.route('/')
@validate_token()
def index():
return 'hi'
if __name__ == '__main__':
app.run(debug=True)
/third_part/example.py
from functools import wraps
def 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 app
app.testing = True
def 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 wraps
from mock import patch
def mock_decorator():
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
return f(*args, **kwargs)
return decorated_function
return decorator
patch('third_part.example.validate_token', mock_decorator).start()
# !important thing - import of app after patch()
from app import app
app.testing = True
def test_index():
with app.test_client() as client:
client.get('/')
Second way(without patch
). tests.py:
from functools import wraps
from third_part import example
def 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 replace
example.validate_token = mock_decorator
from app import app
app.testing = True
def 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.
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