yel*_*ion 4 python unit-testing flask
我有一个security.py定义装饰器的python 模块authorized()。
我想测试装饰器。装饰器将收到一个 Flask 请求标头。装饰器是这样的:
def authorized():
def _authorized(wrapped_func):
def _wrap(*args, **kwargs):
if 'token' not in request.headers:
LOG.warning("warning")
abort(401)
return None
return wrapped_func(*args, **kwargs)
return _wrap
return _authorized
Run Code Online (Sandbox Code Playgroud)
我想使用@patch装饰器模拟 Flask 请求标头。我编写的测试是这样的:
@patch('security.request.headers', Mock(side_effect=lambda *args, **kwargs: MockHeaders({})))
def test_no_authorization_token_in_header(self):
@security.authorized()
def decorated_func(token='abc'):
return access_token
result = decorated_func()
self.assertEqual(result, None)
class MockHeaders(object):
def __init__(self, json_data):
self.json_data=json_data
Run Code Online (Sandbox Code Playgroud)
但我总是收到以下错误:
name = 'request'
def _lookup_req_object(name):
top = _request_ctx_stack.top
if top is None:
raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
Run Code Online (Sandbox Code Playgroud)
我该怎么做才是正确的呢?
模拟整个请求对象以避免触发上下文查找:
@patch('security.request')
Run Code Online (Sandbox Code Playgroud)
并从那里构建模拟:
@patch('security.request')
def test_no_authorization_token_in_header(self, mock_request):
mock_request.headers= {}
@security.authorized()
def decorated_func(token='abc'):
return token
self.assertRaises(Abort):
result = decorated_func()
Run Code Online (Sandbox Code Playgroud)
由于缺少令牌会导致Abort引发异常,因此您应该明确测试这一点。请注意,该request.headers属性不会在任何地方被调用,因此side_effectorreturn_value属性在这里不适用。
我MockHeaders完全忽略了;您的装饰器未使用json_data,并且您的实现缺少__contains__方法,因此in测试无法对此进行测试。一个普通的字典足以满足当前测试的代码。
旁注:authorized是一个装饰器工厂,但它不带任何参数。如果你根本不使用那里的工厂,那就更清楚了。您还应该使用它functools.wraps()来确保其他装饰器添加的任何元数据都能正确传播:
from functools import wraps
def authorized(wrapped_func):
@wraps(wrapped_func)
def _wrap(*args, **kwargs):
if 'token' not in request.headers:
LOG.warning("warning")
abort(401)
return None
return wrapped_func(*args, **kwargs)
return _wrap
Run Code Online (Sandbox Code Playgroud)
然后直接使用装饰器(所以没有调用):
@security.authorized
def decorated_func(token='abc'):
return access_token
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2284 次 |
| 最近记录: |