Flask Blueprint的测试给出了属性错误

时间:2018-05-07 15:58:41

标签: python flask python-unittest python-decorators

我正在使用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 

这是我测试中的import语句:

app_ = define_test_app()
from api.metrics.views import stats
app_.register_blueprint(stats)

非常感谢帮助,因为我完全陷入了困境。

2 个答案:

答案 0 :(得分: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有一个属性。

答案 1 :(得分:0)

当您致电注册蓝图时出错,而不是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()