Flask-SQLAlchemy集成测试无法找到回滚更改的方法

Ser*_*ets 6 python unit-testing sqlalchemy flask flask-sqlalchemy

我正在尝试学习烧瓶技术堆栈,对于我的应用程序,我正在使用Flask-SQLAlchemy.一切都很完美,但我正在努力编写集成测试.我不想使用SQLite,因为在生产中我正在使用PostgreSQL并且放置大量的模拟实际上会更多地测试我自己的实现而不是逻辑本身.

因此,经过一些研究后,我决定实施将在测试数据库中写入数据的测试,并在每次测试后回滚更改(出于性能的考虑).实际上,我正在尝试实现类似于这种方法的东西:http://sontek.net/blog/detail/writing-tests-for-pyramid-and-sqlalchemy.

我的问题是创建正确的事务并能够回滚它.这是我的基类的代码:

from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class MyAppIntegrationTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2:///db_test'
    init_app()
    db.app = app
    db.create_all(app=app)

    @classmethod
    def tearDownClass(cls):
        db.drop_all(app=app)

    def setUp(self):
        db.session.rollback()
        self.trans = db.session.begin(subtransactions=True)

    def tearDown(self):
        self.trans.rollback()
Run Code Online (Sandbox Code Playgroud)

当我尝试执行测试时,出现以下错误:

Traceback (most recent call last):
 File "myapp/src/core/tests/__init__.py", line 53, in tearDown
   self.trans.rollback()
 File "myapp/venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 370, in rollback
   self._assert_active(prepared_ok=True, rollback_ok=True)
 File "myapp/venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 203, in _assert_active
   raise sa_exc.ResourceClosedError(closed_msg)
ResourceClosedError: This transaction is closed
Run Code Online (Sandbox Code Playgroud)

我敢打赌,这是scoped_session的问题,当我运行测试时,它会为所有测试重用一个全局会话,但我在SQLAlchemy中的知识还不够深入.

任何帮助将非常感谢!谢谢!

Adr*_*laz 0

您是tearDownClass 和setUpClass 导致了问题。

setUpClass 在所有测试之前调用一次,tearDownClass 在类中的所有测试之后调用。

所以如果你有 3 个测试。

setUpClass 被调用

设置被调用

调用tearDown(您回滚,但不开始会话,这会引发错误)

setUp 被调用(另一个会出错的回滚)

ETC...

添加一个 db.session.begin 到你的tearDown中,你就会没事的。

from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class MyAppIntegrationTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        app.config['TESTING'] = True
        app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2:///db_test'
        init_app()
        db.app = app
        db.create_all(app=app)

    @classmethod
    def tearDownClass(cls):
        db.drop_all(app=app)

    def setUp(self):
        db.session.rollback()
        self.trans = db.session.begin(subtransactions=True)

    def tearDown(self):
        self.trans.rollback()
        db.session.begin()
Run Code Online (Sandbox Code Playgroud)