【问题标题】:Mock authentication decorator in unittesting单元测试中的模拟身份验证装饰器
【发布时间】:2017-12-20 07:20:59
【问题描述】:

我想在为一个视图编写单元测试时模拟 validate_token 装饰器

#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)

这里的 validate_token 是一个 thirtd_party 模块来授权请求​​,并且令牌是由第三方发布的,所以我不想为我的测试执行 validate_token 装饰器

以下是我的示例测试代码。

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

我在运行测试时尝试模拟
但它没有按预期工作,它给出 401 错误。

如何模拟/修补装饰器以进行测试 这里缺少什么

提前致谢。

【问题讨论】:

标签: python unit-testing flask mocking pytest


【解决方案1】:

这里有一个可以帮助你的例子。以下文件结构。

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('/')

运行我们的tests.py(只要确保装饰器有效):

    @wraps(func)
    def wrapper(*args, **kwargs):
>       raise Exception('Token error. Just for example')
E       Exception: Token error. Just for example

第一种方式如何跳过装饰器(使用patch)。测试.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('/')

第二种方式(不带patch)。测试.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('/')

运行我们的 test.py(以 2 种方式):

tests.py .                                                               [100%]

=========================== 1 passed in 0.09 seconds ===========================

总结。如您所见,非常重要的是何时替换功能。顺便说一句,你试图修补 validate_tokenviews 模块,而不是 third_part.module

希望这会有所帮助。

【讨论】:

  • 谢谢,这很有帮助。但是,如果 mock_decorator 具有依赖于 app 的功能怎么办?在我的情况下,我想用一个从测试数据库返回第一个用户的假装饰器替换我原来的 authorize 装饰器。没有应用程序上下文,我无法使用数据库。如何使用您的方法来实现这一点?
  • @PeterSobhi 我明白这个问题,但你能告诉你你的mock_decorator吗?我需要看代码。请给我一个指向您问题的链接。
  • 这是我同事提出的问题的链接:stackoverflow.com/questions/55597216/…
  • 非常感谢,我正在寻找几个小时来让它工作并且你对其进行了排序...cache = Cache() cache.memoize = mock.patch('flask_caching.Cache.memoize', mocked_memoize).start() 然后我可以将缓存对象传递给使用装饰器的类.. .
猜你喜欢
  • 2016-08-20
  • 2016-04-04
  • 2020-08-13
  • 1970-01-01
  • 2018-02-14
  • 2021-12-23
  • 2016-08-12
  • 2011-03-02
  • 2011-08-08
相关资源
最近更新 更多