对 Flask 蓝图的测试给出了属性错误
Posted
技术标签:
【中文标题】对 Flask 蓝图的测试给出了属性错误【英文标题】:Tests for Flask Blueprint gives attributeerror 【发布时间】:2018-10-17 11:52:57 【问题描述】:我正在使用 Python3.6 中的 unittest 为我的应用程序编写测试。我正在为此测试创建一个简单的 Flask 应用程序,我想用它来注册我定义的蓝图。我遇到的问题是当我尝试导入我的蓝图时:
File "/app/test/__init__.py", line 1, in <module>
from . import test_views
File "/app/test/test_views.py", line 50, in <module>
from api.metrics.views import stats
File "/app/api/metrics/__init__.py", line 1, in <module>
from .views import stats
File "/app/api/metrics/views.py", line 13, in <module>
def get_stats(client=None):
File "/testenv/lib/python3.6/site-packages/flask/blueprints.py", line 161, in decorator
endpoint = options.pop("endpoint", f.__name__)
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 584, in __getattr__
raise AttributeError(name)
AttributeError: __name__
错误出现在我在这段代码中调用 @stats.route... 的地方:
stats = Blueprint('metrics', __name__)
@stats.route('/metrics', methods=['POST'])
@setup.require_suth
def get_metrics(client=None):
<This code is not relevant>
有人知道如何正确执行此操作吗?我真的不知道该怎么做。
这是我的结构:
/app
/api
/metrics
__init__.py
views.py
/test
test_views.py
这是我测试中的导入语句:
app_ = define_test_app()
from api.metrics.views import stats
app_.register_blueprint(stats)
不胜感激,因为我完全被困在这一点上。
【问题讨论】:
【参考方案1】:不要用相同的名字命名模块、目录和蓝图。
基本上我们的代码有这种结构。子树使其更简单。
-- webcompat
|-- __init__.py
|-- form.py
|-- api
| |-- __init__.py
| |-- uploads.py
| |-- endpoints.py
…
|-- helpers.py
|-- views.py
所以在webcompat/__init__.py
from webcompat.api.endpoints import api
app = Flask(__name__, static_url_path='')
app.register_blueprint(api)
在webcompat/api/endpoints/__init__.py
from webcompat.helpers import cool_feature
api = Blueprint('api', __name__, url_prefix='/api')
@api.route('blah')
def somewhere(foo):
"""blablah"""
yeah = cool_feature()
那么这里发生了什么? 模块和蓝图共享相同的名称。所以如果在测试中我们需要模拟cool_feature:
with patch('webcompat.api.endpoints.cool_feature') as mock_cool:
我们需要记住,在模拟时,我们不会模拟已定义的功能(也称为 webcompat.helpers.cool_feature
),而是在其已导入的位置(又名 webcompat.api.endpoints.cool_feature
)模拟。在这种情况下我们将无法模拟,因为会有名称冲突。错误将是:
E AttributeError: 'Blueprint' object has no attribute 'endpoints'
因为命名的webcompat.api
蓝图没有属性endpoints
,而模块webcompat.api
有一个。
【讨论】:
【参考方案2】:当你调用注册你的蓝图时出错,而不是app_.register_blueprint
,只需使用app.register_blueprint
,试试这个:
/app
/api
/metrics
__init__.py
views.py
views.py
from flask import Blueprint
stats = Blueprint('metrics', __name__)
@stats.route('/metrics', methods=['GET', 'POST'])
def get_metrics(client=None):
return 'Hello'
/app
/test
test.py
test.py
from flask import Flask
app = Flask(__name__)
from api.metrics.views import stats
app.register_blueprint(stats)
if __name__ == '__main__':
app.run()
【讨论】:
以上是关于对 Flask 蓝图的测试给出了属性错误的主要内容,如果未能解决你的问题,请参考以下文章
python | 对 Flask 蓝图(Blueprint)的理解
python-flask复习—— 装饰器的坑及解决办法flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件重定义错误页面)