Flask-测试和 Flask-SQLAlchemy:first_or_404()

Joh*_*han 4 python flask flask-sqlalchemy flask-testing

我正在尝试使用Flask-Testing Flask-SQLAlchemy模型进行测试。更准确地说,该模型使用静态方法first_or_404(),但我无法找到使我的测试工作的方法。

这是一个突出问题的独立示例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask.ext.testing import TestCase

db = SQLAlchemy()

class ModelToTest(db.Model):
    __tablename__ = 'model_to_test'
    identifier = db.Column(db.String(80), unique=True, nullable=False, primary_key=True)

    @staticmethod
    def get_by_identifier(identifier):
        return ModelToTest.query.filter_by(identifier=identifier).first_or_404()

class Config:
    DEBUG = True
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class TestGetByIdentifier(TestCase):

    def create_app(self):
        app = Flask('test')
        app.config.from_object(Config())
        db.init_app(app)
        return app

    def setUp(self):
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

    def test_get_by_identifier(self):
        self.assert404(ModelToTest.get_by_identifier('identifier'))
Run Code Online (Sandbox Code Playgroud)

我收到错误:

(my_env) PS C:\Dev\Test\Python\test_flask> nosetests-3.4.exe
E
======================================================================
ERROR: test_get_by_identifier (test_flask.TestGetByIdentifier)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Dev\Test\Python\test_flask\test_flask.py", line 37, in test_get_by_identifier
    self.assert404(ModelToTest.get_by_identifier('identifier'))
  File "C:\Dev\Test\Python\test_flask\test_flask.py", line 13, in get_by_identifier
    return ModelToTest.query.filter_by(identifier=identifier).first_or_404()
  File "c:\\my_env\lib\site-packages\flask_sqlalchemy\__init__.py", line 431, in first_or_404
    abort(404)
  File "c:\\my_env\lib\site-packages\werkzeug\exceptions.py", line 646, in __call__
    raise self.mapping[code](*args, **kwargs)
werkzeug.exceptions.NotFound: 404: Not Found

----------------------------------------------------------------------
Ran 1 test in 0.913s
Run Code Online (Sandbox Code Playgroud)

因此,该行self.assert404(ModelToTest.get_by_identifier('identifier'))确实在调用中生成了一个异常first_or_404(),并且该异常是 a werkzeug.exceptions.NotFound,它似乎不是 所期望的self.assert404()。

运行此测试的要求是:

  • 烧瓶
  • Flask-sqlalchemy
  • 烧瓶测试

值得注意的是,当我在应用程序中使用该函数时,它的行为符合预期。

提前致谢。

Joh*_*han 5

我引用的是我在 GitHub 上收到的答案:

https://github.com/jarus/flask-testing/issues/89

我认为这是对考试方式的误解。该first_or_404函数确实会引发NotFound异常。当在请求的上下文中时,异常将冒泡,被处理,并变成 404 http 响应,这正是 Flask-testing 正在寻找的。

但是,在这种情况下,您并不处于请求的上下文中,因为您直接调用该方法,并且它只会导致异常。你可以这样做来使测试工作

from werkzeug.exceptions import NotFound

def test_get_by_identifier(self):
    with self.assertRaises(NotFound):
        ModelToTest.get_by_identifier('identifier')
Run Code Online (Sandbox Code Playgroud)

或者,您可以将该函数放在路由后面并使用 self.client 进行测试,这将正确地为您提供 404 http 响应。然而,在这种情况下,考虑到您正在测试的级别,测试异常(不使用烧瓶测试)可能更合适。