【发布时间】:2016-04-02 04:50:19
【问题描述】:
我有一个使用 SQLAlchemy 的应用程序,已初始化:
config_name = os.getenv('FLASK_CONFIG') or 'default'
app = Flask(__name__)
db = SQLAlchemy(app)
db.init_app(app)
我正在处理的视图只是以 json 格式返回所有用户:
@app.route('/users', methods=['GET'])
def users():
users = db.session.query(User)
output = {'users': [user.to_json() for user in users]}
return jsonify(**output)
我的测试:
class UserViewTest(BaseTestCase, CreateUserMixin):
def test_users(self):
user1 = self._make_user() # defined in the above mixin
user2 = self._make_user()
user2.email = 'hello@abc.com'
user2.username = 'hello@abc.com'
db.session.add_all([user1, user2])
db.session.flush()
response = app.test_client().get('/users')
我使用FLASK_CONFIG=testing nosetests 运行我的测试(我检查了,app.testing 设置为 true)。
对我的 psql 数据库运行这个,我发现我添加到数据库中的这些用户正在被保存!
triller_social_test=# SELECT username FROM users;
username
---------------
foobar
hello@abc.com
(2 rows)
如何阻止这种情况发生?我尝试覆盖 db.session.commit() 什么都不做,但是当我调用视图时数据库会回滚。有没有使用test_client() 的替代方法?我不能直接调用该方法,因为jsonify 不允许我在响应之外的任何地方返回数据。
更新:这是我的临时(?)解决方案:
def json_response_converter(dict_):
if config_name == 'testing':
return dict_
else:
return jsonify(**dict_)
现在我不需要在我的测试中使用 jsonify()
【问题讨论】:
-
您可以调用
db.session.delete(object)作为测试用例清理的一部分。或者调用session.rollback()应该恢复任何尚未提交的事务更改。 -
我实际上在我的 setUp() 和 tearDown() 上都做了一个 rollback() 以防万一。我可以执行 delete(),但我不希望跟踪创建的每个对象然后再删除它。
-
替代方法是覆盖 SQLAlchemy 配置以使用单独的数据库进行测试。在单元测试中查看Miguel Grinberg's Flask Megatutorial。在他的测试用例设置中,他更改了 SQLAlchemy URI 以使用 SQLite 测试数据库。当然,如果您尝试测试 psql,那将无法达到目的,但这样您就不必担心测试会留在生产数据库中。
-
我确实使用单独的数据库进行测试。不幸的是,我正在测试我在原始 SQL 中所做的某些事情,即一旦创建了用户(在单独的应用程序上 - 这是“管理员”应用程序),通过触发器创建该用户的配置文件。所以使用
db.create_all()和db._drop_all()并不能涵盖我的所有内容。实际上,我使我的测试数据库的迁移与我的主数据库保持同步
标签: python flask flask-sqlalchemy flask-testing