我目前正在使用 pytest 对 Flask 应用程序进行单元测试。但是,当我尝试测试我的路由(似乎是我的任何路由)时,我始终收到 404 Not Found 错误,尽管路由已在测试环境之外定义并按预期工作。我检查了路由注册和应用程序工厂设置,但没有找到问题的原因。
环境:
烧瓶2.x py测试 Python 3.x
配置.py;
class Config:
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
SQLALCHEMY_DATABASE_URI = 'sqlite:////path/to/development.db'
DEBUG = True
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
SQLALCHEMY_TRACK_MODIFICATIONS = False
app.py(为简洁起见,进行了简化):
def create_app(config_class=DevelopmentConfig):
app = Flask(__name__)
app.config.from_object(config_class) # Load the configuration from the provided class
app.config['SQLALCHEMY_DATABASE_URI'] = config_class.SQLALCHEMY_DATABASE_URI
app.config['SECRET_KEY'] = 'your_secret_key'
# Initialize extensions with the app
db.init_app(app)
migrate.init_app(app, db)
return app
app = create_app()
@app.route('/login', methods=['GET', 'POST'])
def login():
# Route implementation
return render_template('login.html')
test_app.py:
import pytest
from apis.stockpulse.app import create_app
from apis.stockpulse.config import TestingConfig
@pytest.fixture
def client():
app = create_app(TestingConfig)
with app.test_client() as client:
with app.app_context():
yield client
def test_login_get(client):
response = client.get('/login')
assert response.status_code == 200 # Fails with 404
问题:
当运行 /login 路由的测试时,pytest 返回 404 状态代码,即使路由已正确定义。我尝试通过在固定装置中使用 app.url_map 打印出所有已注册的路由来进行调试,但似乎仅注册了默认静态路由。
尝试解决:
验证路线定义正确并且在测试之外正常工作。 确保正确应用测试配置,且 TESTING = True。 在测试中检查应用程序上下文是否正确。 尝试显式打印注册的路由,但仅显示静态路由。
我不知道是什么原因导致了这个问题。这是否与我初始化应用程序进行测试的方式有关,或者可能与应用程序上下文未正确封装路由定义有关?任何见解或建议将不胜感激。
app.py
中定义的
app
和在 app
固定装置中创建的 client
是 两个不同的 Flask
实例,并且固定装置的实例没有通过 @app.route
应用的路线装饰器。
解决方案是在测试中使用来自
app.py的相同
app
对象。这显然意味着您需要更改应用程序的配置方式,以便它使用 TestConfig
。不幸的是,我在使用 Flask 时配置它的方式太复杂,无法在这个答案中描述,而且我手头没有其他好的解决方案。
因此,请将以下代码示例视为粗略的修复,而不是作为生产代码的可靠示例:
import pytest
from app import app as real_app
@pytest.fixture(scope="session")
def app():
class TestingConfig:
TESTING = True
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = "xyz"
real_app.config.from_object(TestingConfig)
real_app.test_request_context().push()
return real_app
@pytest.fixture
def client(app):
with app.test_client() as client:
yield client
def test_login_get(client):
response = client.get("/login")
assert response.status_code == 200