我正在使用Flask,SQLAlchemy和Flask-SQLALchemy。由于测试代码和测试共享相同的SQLAlchemy会话,我遇到了几次问题。
以下是一个示例应用程序:
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
db = SQLAlchemy()
db.init_app(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
@app.route('/set_name/<user_id>', methods=['POST'])
def set_name(user_id):
user = User.query.get(user_id)
user.name = request.form['name']
# we don't commit the session, so the name change is only local.
# db.session.commit()
return user.name
示例测试使用单独的上下文作为测试准备代码和测试代码:
def test_set_name_different_context():
with app.app_context():
db.create_all()
user = User(name='a')
db.session.add(user)
db.session.commit()
user_id = user.id
client = app.test_client()
client.post('/set_name/{}'.format(user_id), data={'name': 'b'})
with app.app_context():
user = User.query.get(user_id)
assert user.name == 'a'
在上面的测试中,我们预计名称更改不会持续存在。
但是如果我们改变上面的测试以使用单个上下文(以避免样板):
def test_set_name_same_context():
with app.app_context():
db.create_all()
user = User(name='a')
db.session.add(user)
db.session.commit()
user_id = user.id
client = app.test_client()
client.post('/set_name/{}'.format(user_id), data={'name': 'b'})
user = User.query.get(user_id)
# This fails, because we are in the same app context, we use the
# same session both for the test code and the tested code.
assert user.name == 'a'
测试失败,因为测试代码和测试代码的SQLAlchemy会话是相同的。
虽然你理解会话范围在Flask-SQLAlchemy中是如何工作的,但我仍然想知道是否有办法为测试代码和测试代码提供不同的会话而没有所有的样板。