Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock authentication decorator in unittesting

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.

like image 263
sunny Avatar asked Dec 20 '17 07:12

sunny


People also ask

What is mock MagicMock?

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.

How does Unittest mock work?

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.

What is Property mock python?

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.


1 Answers

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.

like image 147
Danila Ganchar Avatar answered Oct 26 '22 01:10

Danila Ganchar