【问题标题】:Tests for Flask Blueprint gives attributeerror对 Flask 蓝图的测试给出了属性错误
【发布时间】: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)

不胜感激,因为我完全被困在这一点上。

【问题讨论】:

    标签: python flask python-unittest python-decorators


    【解决方案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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-27
        相关资源
        最近更新 更多